为什么`async / await`在我的情况下不起作用?

时间:2018-02-05 07:16:37

标签: javascript asynchronous async-await ecmascript-2017

我读到async/await,但我是一个关键问题。 首先,我解释一个旧的例子,以显示我的问题的基础,然后我问我的确切问题。

每个人都知道:

console.log('1');
console.log('2');
console.log('3'); // Ex: 123

这很简单,但在下面的情况下:

console.log('1');
setTimeout(()=>{
    console.log('2');
},0);
console.log('3'); // Ex: 132

也很简单,setTimeout函数asynchronousJavaScript从中跳过,在解析后运行其函数,所以我们在2之后看到13

但是,现在我读了async/await,我写了一个这样的函数:

(async function test() {
    console.log('1');
    await setTimeout(()=>{
        console.log('2');
    },0);
    console.log('3');
})(); // Ex: 132

导出也是132,为什么?这是我的问题,为什么32之前运行?我希望在async/await JavaScript等1之后2,然后写3。为什么132

3 个答案:

答案 0 :(得分:8)

await仅在传递给它的值为Promise时暂停。在您的情况下,setTimeout会返回Number,因此请等待它。

正确的代码如下:

async function test() {
    console.log('1');
    await new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('2');
            resolve()
        }, 0);
    });
    console.log('3');
}

答案 1 :(得分:2)

因为setTimeout没有返回承诺。 await x仅在x是承诺时才会等待;如果x不是承诺,那么它(有效地)包含在一个承诺中,就好像你有await Promise.resolve(x)一样。这意味着它后面的代码将尽快异步运行。*

如果您需要setTimeout的承诺版本,请参阅this question's answers。但即使这样,你的test函数也不会使用回调,而只是等待启用promise的超时:

function later(delay) {
    return new Promise(function(resolve) {
        setTimeout(resolve, delay);
    });
}

async function test() {
  console.log("1");
  await later(10);
  console.log("2");
  console.log("3");
}

test().catch(e => console.error(e));
console.log("After the call (just to prove it does wait for the timeout after 1 and before 2");

*在浏览器上,保证在同一任务期间安排setTimeout(..., 0)之前,因为任务期间安排的承诺回调发生在该任务结束后,在从队列中拾取下一个任务之前(即使下一个任务是在promise回调之前安排的)。更多关于this question's answers中的“macrotasks”和“microtasks”。

答案 2 :(得分:1)

您可以await返回Promise的函数。 setTimeout不会返回Promise。因此,在await之前使用的setTimeout没有意义。

您可以将setTimeout打包成承诺,并通过setTimeout功能致电解决。

(async function test() {
    console.log('1');
    await new Promise((resolve, reject) => { 
         setTimeout(() => {
            console.log('2');
            resolve(); // also can pass a parameter here to get it via await.
         },0);
    });
    console.log('3');
})();