javascript - promise 没有以我期望的方式解决

标签 javascript promise

我有以下内容:

for (let job of jobs) {
  resets.push(
    new Promise((resolve, reject) => {
      let oldRef = job.ref
      this._sequenceService.attachRef(job).then(() => {
        this._dbService.saveDoc('job', job).then(jobRes => {
          console.log('[%s / %s]: %s', oldRef, jobRes['jobs'][0].ref, this._moment.unix(job.created).format('DD/MM/YYYY HH:mm'))
          resolve()
        }).catch(error => {
          reject(error)
        })
      }).catch(error => {
        reject(error)
      })
    })
  )
}

return Promise.all(resets).then(() => {
  console.log('Done')
})

this._sequenceService.attachRef有一个 console.log()称呼。

运行时,我看到了来自 this._sequenceService.attachRef() 的所有控制台日志打电话,然后我在 saveDoc.then() 中看到所有日志称呼。我期待看到他们交替出现。我的理解是根据 this文章, promise 不会按顺序解决,但我不希望我的 promise 得到解决,直到我调用 resolve()所以仍然期望交替日志,即使不是按顺序。

为什么不是这样?

最佳答案

通过避免 promise anti-pattern,您的代码可以写得更清晰在新的手动创建的 promise 中包装 promise 。相反,您只需将外部 promise 插入您的数组,并通过从 .then() 处理程序内部返回它们将内部 promise 链接到外部 promise。这一切都可以像这样简单地完成:

for (let job of jobs) {
    let oldRef = job.ref;
    resets.push(this._sequenceService.attachRef(job).then(() => {
        // chain this promise to parent promise by returning it 
        // inside the .then() handler
        return this._dbService.saveDoc('job', job).then(jobRes => {
            console.log('[%s / %s]: %s', oldRef, jobRes['jobs'][0].ref, this._moment.unix(job.created).format('DD/MM/YYYY HH:mm'));
        });
    }));
}

return Promise.all(resets).then(() => {
    console.log('Done')
}).catch(err => {
    console.log(err);
});

拒绝将自动向上传播,因此您不需要在循环内使用任何 .catch() 处理程序。


至于排序,情况如下:

  • for 循环是同步的。它会立即运行完成。
  • .attachRef() 的所有调用都是异步的。这意味着调用它们只是启动操作,然后它们返回,其余代码继续运行。这也称为非阻塞。
  • 所有 .then() 处理程序都是异步的。他们最早可以在下一个滴答时运行。
  • 因此这解释了为什么首先发生的事情是所有对 .attachRef() 的调用都执行,因为这就是循环所做的。它立即调用所有 .attachRef() 方法。因为他们只是开始他们的操作然后立即返回,for 循环完成它的工作很快启动所有 .attachRef() 操作。
  • 然后,当每个 .attachRef() 完成时,它会触发相应的 .saveDoc() 被调用。
  • .saveDoc() 调用完成之间的相对时间只是一场比赛,取决于他们何时开始(他们的 .attachRef() 在他们之前来了多久花了) 以及他们自己的 .saveDoc() 调用执行了多长时间。所有这些的相对时间可能无法完全预测,特别是如果幕后有一个可以同时处理多个请求的多线程数据库。

相对时间不可预测这一事实不足为奇。您有意并行运行多个两阶段异步操作,这意味着您不关心它们运行或完成的顺序。它们都在相互竞争。如果它们都花费完全相同的时间来执行而没有变化,那么它们可能会以相同的启动顺序完成,但执行时间的任何微小变化肯定会改变完成顺序。如果底层 DB 同时在所有不同的请求之间发生锁争用,那也会大大改变时间。

因此,此代码旨在并行执行操作并在所有操作完成时通知您。从某种意义上说,这意味着您不关心控制事情运行或完成的精确顺序,只有当它们全部完成时。

关于javascript - promise 没有以我期望的方式解决,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48315459/

相关文章:

javascript - 检测未添加到 DOM 的音频元素

javascript - 将 Promise 函数映射到数组不会保留结果

javascript - 表单提交 - IE 访问被拒绝 - 同一域

javascript - 如何使用 Leaflet 中的自定义控件切换可点击标记属性?

javascript - 当尝试通过node.js使用方法函数时,未定义不是一个函数

javascript - 如何使用 javascript 为 silverlight 插件设置值

javascript - axios IE promise 不起作用

javascript - promise - TypeError : Cannot read property 'then' of undefined

javascript - TypeError : util. promisify 不是函数?

javascript - 有没有一种方法可以结合 Bluebird 的 `then` 和 `catch` 功能?