For the complete documentation index, see llms.txt. This page is also available as Markdown.

异步函数

了解何时以及如何在场景代码中运行异步函数。

概览

你场景中的大部分代码使用单线程同步运行。这意味着命令会按行逐个顺序执行。每个命令都必须先等待前一个命令执行完成,才能开始执行。

即使是场景系统中的函数也会逐个执行,遵循一个 优先级顺序.

同步运行代码可以确保一致性,因为你总能确定代码中的命令会按什么顺序执行。

另一方面,你的场景需要每秒更新多次,以构建下一帧。如果代码中的某一部分响应时间过长,那么整个主线程就会被卡住,从而导致帧率下降、出现卡顿。

因此,在某些情况下,你会希望某些命令异步运行。这意味着你可以先启动一个任务,同时场景可以继续执行后面的代码行。场景仍然在单线程上运行,但当异步任务等待响应时,其余代码不会被阻塞。

这对依赖外部服务、且响应可能需要时间的任务尤其有用,因为你不希望等待响应的空闲时间阻塞其他任务。

例如:

  • 从 REST API 获取数据时

  • 在区块链上执行交易时

运行一个异步函数

将任意函数标记为 异步 ,使其异步运行,在等待期间不会阻塞场景中的其余代码。

// 声明异步函数
async function myAsyncTask() {
	// 执行函数步骤
}

// 调用异步函数
myAsyncTask()

// 其余代码继续执行

executeTask 函数

该 executeTask() 该函数会异步执行一个 lambda 函数。 executeTask() 允许我们在同一个语句中声明并执行函数。

then 函数

该 then 函数将一个 lambda 函数作为参数传入,该 lambda 只有在前一个语句执行完成后才会被执行。这个 lambda 函数可以选择性地带有输入参数,这些参数会从前一个语句返回的内容中映射而来。

PointerEvents 和 RayCast 函数

当你的场景使用 PointerEvent 或 RayCast 组件时,碰撞计算会在引擎中异步完成。随后引擎会向场景返回一个结果事件,而这个事件可能会在触发该事件后的一个或多个游戏循环 tick 之后才到达。

然后你需要创建一个系统,在结果到达的那一帧中对这些结果进行处理。

参见 点击事件 和 射线投射.

💡 提示: 如果射线投射结果的处理需要大量计算(比如运行寻路算法),你可能希望在异步函数中执行该计算。

await 语句

一个 await 该语句会强制执行在继续到下一行代码之前先等待响应。 await 语句只能在异步代码块中使用。

上面的示例执行了一个包含 fetch() 从外部 API 获取数据的操作的函数。 fetch() 该操作是异步的,因为我们无法预测服务器需要多长时间才能响应。不过,在将其解析为 json 之前,下一行需要先获得该操作的输出。这里的 await 语句确保只有在该操作返回值之后,下一行才会运行。同样地, response.json() 函数也是异步的,但下一行需要先完成 json 解析才能打印它。第二个 await 语句会强制下一行只在 json 解析完成后才被调用,无论这需要多长时间。

为函数调用设置超时

使用 setTimeout 用于在某些代码行运行前等待一段时间。这需要两个参数:

  • 要执行的函数

  • 在执行该函数前要等待的毫秒数

下面的示例会等待 1000 毫秒(等于 1 秒),然后执行一个向控制台记录消息的简单函数。

该 clearTimeout 可用于取消一个 setTimeout 仍在等待执行的函数。 setTimeout 会返回一个定时器 id(一个数字),然后你可以将其传递给 clearTimeout。在这种情况下,变量 timeoutId 是在执行 setTimeout时获得的,然后将其传递给 clearTimeout 以取消它。

最后更新于