delayRender() 和 continueRender()
通过调用 delayRender()
,您在表示一个帧不应立即渲染,而应等待异步任务完成。
如果您想在渲染之前调用 API 来获取数据,则此方法很有用。
delayRender()
返回一个句柄。一旦您获取了数据或完成了异步任务,应调用 continueRender(handle)
,以通知 Remotion 您现在已准备好进行渲染。
示例
tsx
import {useCallback ,useEffect ,useState } from "react";import {continueRender ,delayRender } from "remotion";export constMyVideo = () => {const [data ,setData ] =useState (null);const [handle ] =useState (() =>delayRender ());constfetchData =useCallback (async () => {constresponse = awaitfetch ("http://example.com/api");constjson = awaitresponse .json ();setData (json );continueRender (handle );}, []);useEffect (() => {fetchData ();}, []);return (<div >{data ? (<div >This video has data from an API! {JSON .stringify (data )}</div >) : null}</div >);};
tsx
import {useCallback ,useEffect ,useState } from "react";import {continueRender ,delayRender } from "remotion";export constMyVideo = () => {const [data ,setData ] =useState (null);const [handle ] =useState (() =>delayRender ());constfetchData =useCallback (async () => {constresponse = awaitfetch ("http://example.com/api");constjson = awaitresponse .json ();setData (json );continueRender (handle );}, []);useEffect (() => {fetchData ();}, []);return (<div >{data ? (<div >This video has data from an API! {JSON .stringify (data )}</div >) : null}</div >);};
超时
您需要在页面加载后的 30 秒内调用 continueRender()
。这是 puppeteer 的默认超时时间,如果您忘记调用 continueRender()
,它将抛出异常。您可以自定义超时时间。
如果在超时帧内未调用 continueRender()
,渲染将失败,并显示类似于以下内容的异常:
A delayRender() was called but not cleared after 28000ms. See https://remotion.dev/docs/timeout for help. The delayRender was called
A delayRender() was called but not cleared after 28000ms. See https://remotion.dev/docs/timeout for help. The delayRender was called
请查看超时页面以解决超时问题。
添加标签v2.6.13
如果遇到超时问题并且不知道其来源,可以将标签作为参数添加:
tsx
delayRender ("Fetching data from API...");
tsx
delayRender ("Fetching data from API...");
如果调用超时,错误消息中将引用该标签:
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
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
并发
用于渲染的是多个页面,因此可以多次调用 delayRender() 进行渲染。如果正在进行 API 请求,可以通过缓存请求来加快渲染速度并避免速率限制,例如通过将数据存储在 localStorage
中。
多次调用
您可以多次调用 delayRender()
。只要至少存在一个阻塞句柄且尚未通过 continueRender()
清除,渲染将被阻塞。
tsx
import {useEffect ,useState } from "react";import {continueRender ,delayRender } from "remotion";constMyComp :React .FC = () => {const [handle1 ] =useState (() =>delayRender ());const [handle2 ] =useState (() =>delayRender ());useEffect (() => {// You need to clear all handles before the render continuescontinueRender (handle1 );continueRender (handle2 );}, []);return null;};
tsx
import {useEffect ,useState } from "react";import {continueRender ,delayRender } from "remotion";constMyComp :React .FC = () => {const [handle1 ] =useState (() =>delayRender ());const [handle2 ] =useState (() =>delayRender ());useEffect (() => {// You need to clear all handles before the render continuescontinueRender (handle1 );continueRender (handle2 );}, []);return null;};
封装
您应该将 delayRender()
调用放在组件内部,而不是将其放在顶层语句中,以避免在渲染不同组合时阻塞渲染。此外,在下面的示例中,调用被包裹在 useState()
中,以避免在组件重新渲染时创建多个阻塞调用。
❌ 不要这样做tsx
import {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;};
❌ 不要这样做tsx
import {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;};
出现错误时v3.3.44
如果您的代码未能执行异步操作并且您希望取消渲染,您可以调用带有错误消息的 cancelRender()
。这将自动取消所有 delayRender()
调用,以避免进一步延迟渲染。
MyComposition.tsxtsx
importReact , {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;};
MyComposition.tsxtsx
importReact , {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
如果某个操作不稳定(例如,从 CDN 加载资源有时会出现 5xx 错误),您可以传递一个带有 retries
值的对象作为第二个参数。
如果 delayRender()
调用在超时内未清除,则整个浏览器选项卡将被关闭,并且将从头开始重试帧。
重试 delayRender()tsx
import {delayRender } from "remotion";delayRender ("Loading asset...", {retries : 1, // default: 0});
重试 delayRender()tsx
import {delayRender } from "remotion";delayRender ("Loading asset...", {retries : 1, // default: 0});
<Img>
、<Audio>
、<Video>
和 <IFrame>
标签支持一个 delayRenderRetries
属性,用于控制这些组件进行的 delayRender()
调用的 retries
值。
修改超时时间v4.0.140
除了可以设置的全局超时时间,超时时间可以在每个 delayRender()
级别上进行修改。
修改 delayRender() 的超时时间tsx
import {delayRender } from "remotion";delayRender ("Loading asset...", {timeoutInMilliseconds : 7000,});
修改 delayRender() 的超时时间tsx
import {delayRender } from "remotion";delayRender ("Loading asset...", {timeoutInMilliseconds : 7000,});
<Img>
、<Audio>
、<Video>
和 <IFrame>
标签支持一个 delayRenderTimeoutInMilliseconds
属性,用于控制这些组件进行的 delayRender()
调用的 timeoutInMilliseconds
值。```
与 useBufferState().delayPlayback()
的区别
useBufferState()
是一个不同的 API,允许在 Studio 和 Player 中暂停播放。
如果您正在加载数据,您可能希望在渲染过程中延迟组件的截图,并在预览期间启动缓冲状态,在这种情况下,您需要同时使用这两个 API。
同时使用 delayRender() 和 delayPlayback()tsx
importReact from "react";import {useBufferState ,delayRender ,continueRender } from "remotion";constMyComp :React .FC = () => {constbuffer =useBufferState ();const [handle ] =React .useState (() =>delayRender ());React .useEffect (() => {constdelayHandle =buffer .delayPlayback ();setTimeout (() => {delayHandle .unblock ();continueRender (handle );}, 5000);return () => {delayHandle .unblock ();};}, []);return <></>;};
同时使用 delayRender() 和 delayPlayback()tsx
importReact from "react";import {useBufferState ,delayRender ,continueRender } from "remotion";constMyComp :React .FC = () => {constbuffer =useBufferState ();const [handle ] =React .useState (() =>delayRender ());React .useEffect (() => {constdelayHandle =buffer .delayPlayback ();setTimeout (() => {delayHandle .unblock ();continueRender (handle );}, 5000);return () => {delayHandle .unblock ();};}, []);return <></>;};