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

Posted

技术标签:

【中文标题】为啥 `async/await` 在我的情况下不起作用?【英文标题】:Why `async/await` doesn't work in my case?为什么 `async/await` 在我的情况下不起作用? 【发布时间】:2018-07-15 00:13:06 【问题描述】:

我读到了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从中跳转,解析后运行它的函数,所以我们在13之后看到2

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

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

导出也是132,为什么?这是我的问题,为什么32 之前运行?我期望因为async/await1 之后JavaScript 等待2 然后写3。为什么132

【问题讨论】:

异步函数是 ES2017 的一部分,而不是 ES7 (ES2016)。 @FelixKling,谢谢,我很困惑,ES2017 是不是叫ES8 【参考方案1】:

await 仅在传递给它的值为Promise 时才会挂起。在你的情况下,setTimeout 返回一个 Number 所以 await 不会等待它。

正确的代码如下:

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

【讨论】:

【参考方案2】:

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

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

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。

【讨论】:

【参考方案3】:

您可以await 到返回Promise 的函数。 setTimeout 不返回 Promise。所以在这种情况下awaitsetTimeout 之前使用是没有意义的。

您可以将您的 setTimeout 包装到 Promise 中并在 setTimeout 函数中调用 resolve。

(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');
)();

【讨论】:

以上是关于为啥 `async/await` 在我的情况下不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

.push() 在 throw 下不起作用,使用 async await 方法在 javascript 中循环获取数据

Gulp/Typescript/Async/Await 代码不起作用 - 为啥?

为啥我的 JRadioButton 在这种情况下不起作用?

为啥 selectAnnotation 在这种情况下不起作用?

为啥 Async Await 可以与 React setState 一起使用?

res.download() 在我的情况下不起作用