在Javascript中没有等待的异步功能

时间:2017-08-09 15:15:53

标签: javascript asynchronous async-await

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

function someMath() {
  for (let i = 0; i < 3000000; 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() {
  a()
  console.log('after a (no await) call')
}

bButton.onclick = function() {
  b()
  console.log('after b (await) call')
}
<button id="aButton">test without await</button>
<button id="bButton">test with await</button>
<button id="clear">clear console</button>

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

所以我的问题是:当没有async关键字时,javascript如何执行await功能?

真实用例:我有一个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()

P.S:标题有javascript关键字,以避免与其他语言中的相同问题混淆(即Using async without await

4 个答案:

答案 0 :(得分:21)

来自mozilla doc:

  

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

正如您所假设的,如果没有等待,则执行不会暂停,您的代码将同步执行。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function#Description

答案 1 :(得分:7)

在执行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是异步的,其余所有都是同步的,包括承诺,因此输出是

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

答案 2 :(得分:6)

使用或不使用await执行相同的功能。 await所做的是自动等待要解析的函数返回的承诺。

await timeout(1000);
more code here;

大致相当于:

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

async function声明只是让函数自动返回一个在函数返回时解析的promise。

答案 3 :(得分:4)

正如其他答案所说/表明的那样: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);