如何在 Javascript 中创建异步函数?
JavaScript 是一种单线程的同步语言。代码一次按一个顺序执行。但在某些情况下,Javascript 可能看起来是异步的。
例子:
HTML
HTML
HTML
HTML
HTML
输出
f2 is starting
f2 is ending
f1 is starting
f1 is ending
现在,我们可以看到在执行 setTimeout(f1, 100) 之后,我们的程序并没有等待计时器完成它,而是立即跳转到下一条语句。发生这种情况是因为如果我们想要执行某个事件,JavaScript 会将事件放入事件队列并继续正常执行程序。引擎会定期在事件队列中查看是否需要调用某个事件。
但是我们可能希望我们的程序等到某些特定事件或工作完成后再处理进一步的命令。
异步函数是使用 async、await 和 Promise 实现的。
- async: “async”关键字定义了一个异步函数。
Syntax
async function FunctionName(){
...
}
- await: “async”函数包含“await”,它暂停“async”函数的执行。 “await” 仅在“async”函数内部有效。
- Promise: Promise 是一个代理值。它告诉我们异步事件的成功/失败。 Promise 必须包含resolve()或reject()调用,否则 Promise 的使用者将永远不会知道 Promise 是否已实现。如果发生这种情况,那么程序将继续等待 await 并且该代码块将永远不会被进一步执行。 Promise 还有很多东西,但我们可以在没有任何深入了解的情况下制作异步函数。
示例:让我们使用异步函数重做上面的示例。
HTML
输出:
f2 is starting
f1 is starting
f1 is ending
f2 is ending
在上面的示例中,程序等待 f1() 完成其执行,然后再继续执行。 “等待”会停止执行该代码段,直到收到 Promise。 resolve() 用于解析 Promise。这意味着承诺已经实现。与 resolve 类似,我们也可以使用 reject() 来知道 Promise 被拒绝。 reject()函数主要用于调试和错误目的,我们暂时不需要深入研究它。
示例:如果我们希望 Promise 返回某个值,我们可以在 resolve(variable) 中传递它。
HTML
输出:
f2 is starting
f1 is starting
f1 is ending
Promise Received
f2 is ending
等待多个 Promise:如果我们必须等待多个函数怎么办?我们有两种方法。
示例:我们可以顺序编写多个 await 语句。
HTML
输出
f2 is starting
f1 is starting
f1 is ending
f3 is starting
f3 is ending
f2 is ending
- 在上面的例子中,首先我们得到
f2 is starting
- 然后1秒后我们得到
f1 is starting
f1 is ending
- 然后再过 1 秒,我们得到
f3 is starting
f3 is ending
f2 is ending
示例:等待多个 Promise 的第二种方法是使用 Promise.all(iterable object) 并行运行 Promise。
句法:
await Promise.all(iterable object);
例子:
HTML
输出
f2 is starting
f1 is starting
f1 is ending
f3 is starting
f3 is ending
f2 is ending
- 输出和前面的代码一样,但是在这种情况下,程序会输出
f2 is starting
- 然后等待1秒并输出
f1 is starting
f1 is ending
f3 is starting
f3 is ending
f2 is ending
由于 f1() 和 f3() 是并行运行的,因此我们无需再等待 1 秒即可执行 f3()。简单来说就是f1()和f3()中setTimeout()的定时器同时启动。
注意:我们也可以仅使用 Promises 实现异步行为,而无需 async/await 和回调,请参阅以下链接:
- https://www.geeksforgeeks.org/javascript-callbacks/
- https://www.geeksforgeeks.org/javascript-promises/