猿问

JS:我的 setTimeout 在闭包循环中出现问题

我正在练习一些 Promise 和 Closure。我有一个forEach循环,返回一个 3 秒超时的 Promise,在 Promise 解析后,它应该记录一条语句。


我认为我这样做是错误的,因为我期望每 3 秒看到一个日志,"111"然后是"222",但是我看到延迟了 3 秒,然后立即看到 3 个日志"111" "222"。


let arr = [1,2,3];


arr.forEach((x,i) => {

  (function() {

       return new Promise((resolve,reject) => {

          setTimeout(() => {

             console.log("111")

             resolve(true)

          }, 3000);

       })


  })()

  .then(() => {console.log("222")})

});


MM们
浏览 125回答 1
1回答

弑天下

您只是忘记告诉 javascript 在 for 循环的每次迭代之间“等待”超时。那么发生了什么,javascript 将运行 for 循环,同时安排三个超时,然后这三个超时全部立即消失。如果您像这样添加等待,那么它将按您的预期工作。(async function() {  let arr = [1, 2, 3];  for (let x of arr) {    await (function() { // <-- await added      return new Promise((resolve, reject) => {        setTimeout(() => {          console.log("111")          resolve(true)        }, 3000);      })    })()    .then(() => {      console.log("222")    })  }})()我切换到 for-of,因为 .forEach() 不适用于异步函数。我还将整个内容包装在 async IIFE中,因为那里不允许顶级等待 - 根据您放置此代码的位置,您可能不必将其包装在 async IIFE 中。编辑刚刚意识到,您在原始问题中的任何地方都没有使用异步/等待内容。我不知道你是否已经了解了它,但你不必知道它来解决这个特定的问题。这是另一种无需异步/等待的方法。let arr = [1, 2, 3];let promise = Promise.resolve();arr.forEach((x,i) => {  promise = promise    .then(function() {      return new Promise((resolve, reject) => {        setTimeout(() => {          console.log("111")          resolve(true)        }, 3000);      })    })    .then(() => {      console.log("222")    })});这基本上是在循环内构建一个承诺链。如果您“展开”循环,它将如下所示:promise = Promise.resolve()promise = promise  .then(() => /* wait 3000 ms and log "111" */)  .then(() => { console.log("222") })  .then(() => /* wait 3000 ms and log "111" */)  .then(() => { console.log("222") })  .then(() => /* wait 3000 ms and log "111" */)  .then(() => { console.log("222") })因为我们保留了对最后一个承诺的引用,并且我们不断地附加到它的末尾,所以我们附加的每件新事情都会在最后一件事情完成后发生。
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答