【问题标题】:Why Async does not work in my case (Node js)?为什么异步在我的情况下不起作用(Node js)?
【发布时间】:2019-07-08 22:54:00
【问题描述】:

我是 Node.js 异步/等待的新手。我很难理解 async/await 是如何工作的。如果有人能指出我的学习方向,将不胜感激。

async function loop() {
  let i = 0;
  while (i < 10000) {
    i++;
  }
  console.log('step 2');
}

console.log('step 1');
loop();
console.log('step 3');

期望 : 'step 1', 'step 3', 'step 2' 按顺序打印,但它正在打印 'step 1', 'step 2', 'step 3' 就好像它是同步的。

【问题讨论】:

  • 同步的,你没有任何异步或在函数内部等待。
  • await i++... 一个没有任何异步的async 函数没有多大意义。
  • async 不会导致函数在另一个线程中运行。 JavaScript 是单线程,所以没有任何异步等待,函数仍然同步运行。您可能在这里将“异步”与“多线程”混淆了。
  • @trincot 虽然将await 添加到不返回 Promise 的东西不是语法错误,但它也不会使事情异步。 await i++ 是同步的,因此与 i++ 完全相同(没有等待)
  • @slebetman,然后您会惊讶地看到“step 3”在“step 2”之前输出。 await always 暂停执行它所在的函数,然后立即返回一个承诺。

标签: javascript typescript asynchronous async-await


【解决方案1】:

异步函数会立即执行,并且只有在您到达第一个 await 语句时才会“暂停”。

为此目的使用异步函数并没有多大意义。如果您的目标是稍后执行某些操作,您可能需要process.nextTick

【讨论】:

  • 很抱歉给人的印象是迂腐,我真的不是想把它变成一个论点,我只是想澄清值得注意的 cmets 中可能存在的歧义,这样未来的读者就不会误解断言的含义.我确实认为returnasync 函数中的工作方式确实值得注意,但很容易被误解。
  • @PatrickRoberts - 我猜因为它总是返回一个承诺,你可以认为函数的代码 itself 是同步的,包括 return 如果它在第一个 @987654326 之前到达一个@。我的观点是,async 函数没有 await 仍然返回一个承诺,你只能异步获得该结果。我应该说“当它返回时”而不是 return(因为正如你所说,finally 是同步执行的)但这是评论中的一个小观察。
  • 是的,这是正确的@T.J.Crowder。感谢帕特里克介入,我不认为你是迂腐的。
【解决方案2】:

它按该顺序显示消息,因为没有触发异步操作。 While 循环是同步执行的。 试试这样的:

function timeout(){
    return new Promise((resolve,reject) => {
        setTimeout(() => {
           resolve('step 2')
        }, 1000)  
    })
}

async function loop() {
    const result = await timeout()
    console.log(result)
}

console.log('step 1');
loop();
console.log('step 3');

函数超时正在进行异步操作,您将使用 await 关键字在循环函数中等待该操作完成。

基本上你使用await关键字来等待一些Promise(一些异步操作)被解析,而await关键字只能在异步函数中使用。

我希望这个答案有帮助,我试图以最简单的方式解释它。 :)

【讨论】:

  • 或者,您可以将创建承诺减少到Promise.resolve()
【解决方案3】:

如果你想让loop 异步循环,让它在循环中做一些异步的事情。 async 函数同步运行直到第一个 await(或当它返回时),此时它返回一个完成的承诺。

异步循环有时可以很好地建模为异步生成器函数:

function somethingAsync(value) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(value);
        }, Math.random() * 50);
    });
}
async function* loop() {
    let i = 0;
    while (i < 10) { // made it 10 instead of 10000
        yield somethingAsync(i++);
    }
    console.log('step 2');
}
console.log('step 1');
const gen = loop();
console.log('step 3');
(async () => {
    for await (const value of gen) {
       console.log(value);
    }
})();

在那里,生成器产生下一个值的承诺(显然,somethingAsync 是实际执行某事的占位符,而不仅仅是在延迟后返回值)。使用 for-await-of 可以让您循环遍历生成器返回的承诺的履行值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-09-23
    • 2018-07-15
    • 2021-09-29
    • 2017-02-22
    • 1970-01-01
    • 2016-08-27
    • 1970-01-01
    • 2015-05-26
    相关资源
    最近更新 更多