异步函数内的Javascript setTimeout

问题描述 投票:0回答:2

我看到了很多

setTimeout
即使使用
await
关键字也不等待的问题,答案就像将它与
promise
一起使用,但我仍然不明白。

async
函数不是隐式返回
promise
吗?那么,从下面的代码中,函数
f
里面有一个
setTimeout
返回承诺?并且可以与
await
关键字一起使用。

const f = async(x) => {
    setTimeout(() => {
      console.log(x, 'done!!!')
    }, x)
  }
  (async() => {
    await f(2000)
    await f(1000)
    await f(500)
    console.log('all done!')
  })()

我的预期结果:

2000 已完成!!!

1000 已完成!!!

500 已完成!!!

全部完成!

const f = async(x) => {
  setTimeout(() => {
    console.log(x, 'done!!!')
  }, x)
}

(async() => {
  await (async() => {
    f(2000)
    f(1000)
    f(500)
  })()
  console.log('all done!')
})()

我的预期结果:

500 已完成!!!

1000 已完成!!!

2000 已完成!!!

全部完成!

javascript async-await promise
2个回答
1
投票

异步函数不是隐式返回promise吗?

是的,通过创建一个函数

async
,该函数将返回一个承诺。但如果您的代码中没有任何
await
,则该承诺将立即得到解决。

让我们逐步执行此代码:

async (x) => {
  setTimeout(()=>{console.log(x, 'done!!!')}, x)
}

函数开始运行。它调用

setTimeout
,要求 javascript 在 x 毫秒过后调用函数
() => {console.log(x, 'done!!!')}
。 JavaScript 会记录此请求,并且您的函数将继续。没有更多的代码行,因此您的功能已完成。它隐式返回一个未定义的值,它被包裹在一个承诺中。

最终结果:计时器已启动,但尚未完成,调用

f
的人都会收到处于已解决状态的 Promise。所以
await
这个承诺不会造成任何延迟,因为承诺已经解决了。一段时间后,超时将会消失,console.log 也会发生,但这并不影响
f
返回的 Promise 何时解析。

如果您想设置超时并将其包装在 Promise 中,请使用

new Promise
构造函数:

const f = (x) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(), x);
  });
}

// Or shorter:
const f = (x) => {
  return new Promise((resolve) => {
    setTimeout(resolve, x);
  });
}

当此版本的

f
运行时,您开始创建一个新的 Promise。在构建 Promise 时,您设置了超时并要求 javascript 在 x 毫秒后调用函数。然后你返回这个处于待处理状态的承诺。等待这个承诺将导致您的代码暂停。一段时间后,超时结束,您调用resolve。现在承诺已经解决,因此等待它的任何代码都可以继续。


-1
投票

以下代码将返回如下结果。

output:-

这是因为事件循环处理而不是异步/等待。

是的,异步函数隐式返回一个 Promise,但是您必须使用“then”来顺序执行。

© www.soinside.com 2019 - 2024. All rights reserved.