delayRender() and continueRender()
delayRender() 暂停渲染以让异步任务(例如数据获取)完成。
在预览环境(例如 Studio 或 Player)中,它没有效果。
此 API 返回一个句柄。一旦你获取了数据或完成异步任务,应调用 continueRender(handle) 通知 Remotion 渲染可以继续。
🌐 This API returns a handle. Once you have fetched data or finished the asynchronous task, you should call continueRender(handle) to let Remotion know that the render can continue.
如果异步任务失败且无法恢复,请调用 cancelRender() 来取消渲染。
🌐 If the asynchronous task fails and you cannot recover, call cancelRender() to cancel the render.
delayRender() 可以从 remotion 包中导入,但更推荐你使用 useDelayRender() 钩子,因为它可以为你的代码的 浏览器渲染 做未来兼容性准备。
示例
🌐 Example
import {useCallback , useEffect , useState } from 'react';
import {useDelayRender } from 'remotion';
export const MyVideo = () => {
const [data , setData ] = useState (null);
const {delayRender , continueRender , cancelRender } = useDelayRender ();
const [handle ] = useState (() => delayRender ());
const fetchData = useCallback (async () => {
try {
const response = await fetch ('http://example.com/api');
const json = await response .json ();
setData (json );
continueRender (handle );
} catch (err ) {
cancelRender (err );
}
}, []);
useEffect (() => {
fetchData ();
}, []);
return <div >{data ? <div >This video has data from an API! {JSON .stringify (data )}</div > : null}</div >;
};超时
🌐 Timeout
在调用 delayRender() 之后,你需要在 30 秒内调用 continueRender(),否则渲染将因超时错误而失败。你可以自定义超时。
🌐 After calling delayRender(), you need to call continueRender() within 30 seconds or the render will fail with a timeout error. You can customize the timeout.
如果在超时时间内没有调用 continueRender(),渲染将会失败,并抛出类似这样的异常:
🌐 If continueRender() is not called within the timeout frame, the render will fail with an exception similarly to this:
A delayRender() was called but not cleared after 28000ms. See https://remotion.dev/docs/timeout for help. The delayRender was called请查看 Timeout 页面以排除超时问题。
🌐 See the Timeout page to troubleshoot timeouts.
添加标签v2.6.13
🌐 Adding a labelv2.6.13
如果你遇到超时并且不知道它来自哪里,你可以添加一个标签作为参数:
🌐 If you encounter a timeout and don't know where it came from, you can add a label as a parameter:
delayRender ('Fetching data from API...');如果调用超时,错误消息中将引用该标签:
🌐 If the call times out, the label will be referenced in the error message:
Uncaught Error: A delayRender() "Fetching data from API..." was called but not cleared after 28000ms. See https://remotion.dev/docs/timeout for help. The delayRender was called多次通话
🌐 Multiple calls
你可以多次调用 delayRender()。只要存在至少一个尚未被 continueRender() 清除的阻塞句柄,渲染就会被阻塞。
🌐 You can call delayRender() multiple times. The render will be blocked for as long as at least one blocking handle exists that has not been cleared by continueRender().
import {useEffect , useState } from 'react';
import {useDelayRender } from 'remotion';
const MyComp : React .FC = () => {
const {delayRender , continueRender } = useDelayRender ();
const [handle1 ] = useState (() => delayRender ());
const [handle2 ] = useState (() => delayRender ());
useEffect (() => {
// You need to clear all handles before the render continues
continueRender (handle1 );
continueRender (handle2 );
}, []);
return null;
};封装
🌐 Encapsulation
你应该将 delayRender() 调用放在你的组件内部,而不是作为顶层语句放置,以避免在渲染不同组合时阻塞渲染。
🌐 You should put delayRender() calls inside your components rather than placing them as a top-level statement, to avoid blocking a render if a different composition is rendered.
❌ Bug - Other compositions are blockedimport {useEffect } from 'react'; import {continueRender ,delayRender } from 'remotion'; // Don't call a delayRender() call outside a component - // it will block the render if a different composition is rendered // as well as block the fetching of the list of compositions. consthandle =delayRender (); constMyComp :React .FC = () => {useEffect (() => {continueRender (handle ); }, []); return null; };
还要避免在每次 React 渲染 时创建新的句柄:
🌐 Also avoid creating a new handle on every React render:
❌ Bug - New handle is create on every React re-renderimport {useEffect } from 'react'; import {continueRender ,delayRender } from 'remotion'; constMyComp :React .FC = () => { // New handle is created on every React re-render consthandle =delayRender ();useEffect (() => {continueRender (handle ); }, []); return null; };
最好一开始就使用useDelayRender(),因为这种错误不会发生,并且它将来可以启用浏览器渲染。
🌐 It's best to always use useDelayRender() in the first place since this mistake cannot happen and it enables browser rendering in the future.
✅ Best practice - useDelayRender() + useState()import {useEffect ,useState } from 'react'; import {useDelayRender } from 'remotion'; constMyComp :React .FC = () => { const {delayRender ,continueRender } =useDelayRender (); const [handle ] =useState (() =>delayRender ());useEffect (() => {continueRender (handle ); }, []); return null; };
数据获取
🌐 Data fetching
请注意,数据获取也可以在 calculateMetadata() 中进行,这有两个优点:
🌐 Note that data fetching can also be performed in calculateMetadata(), which has 2 advantages:
- 它只运行一次,而不是并发的数量。
- 你不需要手动调用
continueRender()或cancelRender()。
失败,出现错误v4.0.374
🌐 Failing with an errorv4.0.374
如果你的代码未能执行异步操作,并且你想取消渲染,你可以调用 cancelRender() 并附上错误信息。这将自动取消所有 delayRender() 调用,以避免进一步延迟渲染。
🌐 If your code fails to do an asynchronous operation and you want to cancel the render, you can call cancelRender() with an error message. This will automatically cancel all delayRender() calls to not further delay the render.
MyComposition.tsximportReact , {useEffect ,useState } from 'react'; import {cancelRender ,continueRender ,delayRender } from 'remotion'; export constMyComp :React .FC = () => { const [handle ] =useState (() =>delayRender ('Fetching data...'));useEffect (() => {fetch ('https://example.com') .then (() => {continueRender (handle ); }) .catch ((err ) =>cancelRender (err )); }, []); return null; };
重试v4.0.140
🌐 Retryingv4.0.140
如果一个操作不稳定(例如,从 CDN 加载资源有时会出现 5xx 错误),你可以将一个带有 retries 值的对象作为第二个参数传入。
如果 delayRender() 调用在超时时间内没有被清除,整个浏览器标签页将被关闭,并且该框架将从头重新尝试。
🌐 If an operation is flaky (for example, if loading an asset from a CDN does sometimes give 5xx errors), you can pass an object with a retries value as a second argument.
If a delayRender() call is not cleared within the timeout, the whole browser tab will be closed and the frame will be retried from scratch.
Retrying a delayRender()delayRender ('Loading asset...', {retries : 1, // default: 0 });
<Img>、<Video>、<Audio>、<Html5Audio>、<Html5Video> 和 <IFrame> 标签支持一个 delayRenderRetries 属性,用于控制这些组件所调用的 delayRender() 函数的 retries 值。
🌐 The <Img>, <Video>, <Audio>, <Html5Audio>, <Html5Video> and <IFrame> tags support a delayRenderRetries prop to control the value of retries for the delayRender() call that those components make.
修改超时v4.0.140
🌐 Modifying the timeoutv4.0.140
除了可以设置的全局超时之外,还可以在每个 delayRender() 级别修改超时。
🌐 In addition to the global timeout that can be set, the timeout can be modified on a per-delayRender() level.
Modifying the timeout of a delayRender()delayRender ('Loading asset...', {timeoutInMilliseconds : 7000, });
<Img>、<Video>、<Audio>、<Html5Audio>、<Html5Video> 和 <IFrame> 标签支持一个 delayRenderTimeoutInMilliseconds 属性,用于控制这些组件调用的 delayRender() 方法的 timeoutInMilliseconds 值。
🌐 The <Img>, <Video>, <Audio>, <Html5Audio>, <Html5Video> and <IFrame> tags support a delayRenderTimeoutInMilliseconds prop to control the value of timeoutInMilliseconds for the delayRender() call that those components make.
与useBufferState().delayPlayback()的差异
🌐 Difference to useBufferState().delayPlayback()
[useBufferState()](/docs/use-buffer-state) 是一个不同的 API,它允许在 Studio 和 Player 中暂停播放。
delayRender() 只有在视频正在渲染时才会生效。
如果你正在加载数据,你可能希望在渲染期间延迟截图你的组件,并在预览期间启动缓冲状态,在这种情况下,你需要同时使用这两个 API。
🌐 If you are loading data, you might want to both delay the screenshotting of your component during rendering and start a buffering state during Preview, in which case you need to use both APIs together.
Using delayRender() and delayPlayback() togetherimportReact from 'react'; import {useBufferState ,useDelayRender } from 'remotion'; constMyComp :React .FC = () => { constbuffer =useBufferState (); const {delayRender ,continueRender } =useDelayRender (); const [handle ] =React .useState (() =>delayRender ());React .useEffect (() => { constdelayHandle =buffer .delayPlayback ();setTimeout (() => {delayHandle .unblock ();continueRender (handle ); }, 5000); return () => {delayHandle .unblock (); }; }, []); return <></>; };
兼容性
🌐 Compatibility
| Browsers | Environments | |||||
|---|---|---|---|---|---|---|
Chrome | Firefox | Safari | ||||
Use useDelayRender() | No-op | No-op | ||||
另请参阅
🌐 See also