繁体   English   中英

JavaScript 中没有等待的异步函数

[英]Async function without await in JavaScript

我有两个函数, ab ,它们是异步的,前者没有await ,后者有await 他们都将某些内容记录到控制台并返回undefined 在调用任一函数后,我记录另一条消息并查看该消息是在执行函数主体之前还是之后编写的。

 function someMath() { for (let i = 0; i < 9000000; i++) { Math.sqrt(i**5) } } function timeout(n) { return new Promise(cb => setTimeout(cb, n)) } // ------------------------------------------------- a (no await) async function a() { someMath() console.log('in a (no await)') } // ---------------------------------------------------- b (await) async function b() { await timeout(100) console.log('in b (await)') } clear.onclick = console.clear aButton.onclick = function() { console.log('clicked on a button') a() console.log('after a (no await) call') } bButton.onclick = function() { console.log('clicked on b button') b() console.log('after b (await) call') }
 <button id="aButton">test without await (a)</button> <button id="bButton">test with await (b)</button> <button id="clear">clear console</button>

如果您在没有await的情况下启动测试,该功能似乎就像是同步的一样工作。 但是对于await ,消息会随着函数的异步执行而反转

当没有await关键字时,JavaScript 如何执行async函数?


真实用例:我有一个有条件执行的await关键字,我需要知道该函数是否同步执行才能呈现我的元素:

async function initializeComponent(stuff) {
   if (stuff === undefined)
      stuff = await getStuff()
   // Initialize

   if (/* Context has been blocked */)
       renderComponent() // Render again if stuff had to be loaded
}

initializeComponent()
renderComponent()

PS:标题有 JavaScript 关键字以避免与其他语言中的相同问题混淆(即使用 async without await

Mozilla 文档

异步函数可以包含一个等待表达式,它暂停异步函数的执行并等待传递的 Promise 的解析,然后恢复异步函数的执行并返回解析的值。

正如您所假设的,如果不存在等待,则不会暂停执行,然后您的代码将照常同步执行。

在执行 Javascript 异步函数之前,一切都是同步的。 在使用 async-await 时, await是异步的,await 之后的所有内容都放在事件队列中。 类似于.then()

为了更好地解释,举个例子:

function main() {
  return new Promise( resolve => {
    console.log(3);
    resolve(4);
    console.log(5);
  });
}

async function f(){
    console.log(2);
    let r = await main();
    console.log(r);
}

console.log(1);
f();
console.log(6);

因为await是异步的,而其余的都是同步的,包括 promise,因此输出是

1
2
3
5
6
// Async happened, await for main()
4

main()的类似行为也没有承诺:

function main() {
    console.log(3);
    return 4;
}

async function f(){
    console.log(2);
    let r = await main();
    console.log(r);
}

console.log(1);
f();
console.log(5);

输出:

1
2
3
5
// Asynchronous happened, await for main()
4

只需删除await将使整个async函数同步。

function main() {
    console.log(3);
    return 4;
}

async function f(){
    console.log(2);
    let r = main();
    console.log(r);
}

console.log(1);
f();
console.log(5);

输出:

1
2
3
4
5

无论有无await ,该函数的执行方式都相同。 await所做的是自动等待函数返回的 promise 被解析。

await timeout(1000);
more code here;

大致相当于:

timeout(1000).then(function() {
    more code here;
});

async function声明只是使函数自动返回一个在函数返回时解决的承诺。

正如其他答案所说/表明的那样: async function只是在现场运行,直到遇到await - 如果没有await ,它会完全运行。

可能值得添加的是async无条件地使您的结果成为Promise 所以如果你返回一些东西,已经有区别了,如果不首先返回 JS 引擎,你根本无法得到结果(类似于事件处理):

 async function four(){ console.log(" I am four"); return 4; } console.log(1); let result=four(); console.log(2,"It is not four:",result,"Is it a promise ?", result instanceof Promise); result.then(function(x){console.log(x,"(from then)");}); console.log(3);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM