【问题标题】:Order of async functions execution异步函数执行的顺序
【发布时间】:2019-11-27 09:59:20
【问题描述】:

我正在处理一个旧代码库,并且遇到了这样一种情况,即在解决承诺后我很难理解执行顺序。我更熟悉 async/await 语法或一系列 then-s,但不熟悉这个。这是sn-p:

_loadCaseDetail: funciton (arg1, arg2, arg3) {
  var oDataModel = this.getOwnerComponent().getModel('db2');

  loadLatestDatasetVersion(oDataModel).then(function (datasetVersion) {
    // do something
  });

  loadCountries(oDataModel).then(function (countries) {
    // do something
  });

  numberOfRulesetChanges(oDataModel).then(function (elements) {
    // do something
  });

  return fireImplicitLock(caseUuid).then(function (lockData) {
    // do something
  }).then(function () {
    // do something
  })
}

loadLatestDatasetVersion, loadCountries, numberOfRulesetChanges, fireImplicitLock - 所有返回承诺

我的问题是:在这种情况下,这些承诺之后的所有 then-s 的顺序是什么?

它是否完全按顺序排列,我们可以用Promise.all 重构它吗?

它甚至需要任何重构吗?

【问题讨论】:

  • 这只是从上到下调用​​函数。每个人都在做自己的工作,而不管其他人。 _loadCaseDetailfireImplicitLock() 返回 Promise。如果loadLatestDatasetVersionloadCountriesnumberOfRulesetChangesfireImplicitLock 之间存在任何依赖关系,并且这有效,那么这只是运气......
  • @Andreas 感谢您的回答,所以所有 then-s 也将在浏览器中以相同的自上而下的顺序执行?
  • 没有。谁完成了它的工作就会触发它的.then()。没有具体的顺序。
  • @Andreas 我明白了,所以如果这些 `then` 块中没有耦合代码,我猜它应该可以正常工作
  • 与其说需要重构不如说需要改进。创建了四个 Promise,只返回一个。 _loadCaseDetail 的调用者有权期望所有异步活动都在返回的承诺中表示,而不仅仅是其中的一部分。因此使用Promise.all() 聚合四个promise,并返回由此创建的单个Promise。

标签: javascript promise


【解决方案1】:

在这种情况下,这些承诺之后的所有 then-s 的顺序是什么?

then 函数将在关联的 Promise 解决时触发。这就是异步代码的意义所在。它会消失,直到它准备好做下一件事情。

我们可以用 Promise.all 重构它

您可以使用Promise.all 等到多个promise 解决后再对结果值执行任何操作,但这将是低效的,除非Cthen 函数需要来自AB 的数据。

【讨论】:

  • 感谢@Quentin 的回复。所以没有优先考虑返回的承诺?基本上这是 sn-p 是可能在不同时间点解决的不同内容的集合
  • 没有。承诺只是一个你可以像其他任何东西一样返回的值。没有特殊的外壳。
  • @Ren 是的,这些承诺没有特定的顺序,它们可能会在不同的时间点解决。
【解决方案2】:

loadLatestDatasetVersionloadCountriesnumberOfRulesetChangesfireImplicitLock - 所有返回承诺,它们将一个接一个地插入事件循环。

then 部分承诺将在承诺解决后执行。哪个承诺的then 将被执行取决于各自的promise 的执行。

_loadCaseDetail: funciton (arg1, arg2, arg3) {
  var oDataModel = this.getOwnerComponent().getModel('db2');

  loadLatestDatasetVersion(oDataModel).then(function (datasetVersion) {
    // do something
  });

  loadCountries(oDataModel).then(function (countries) {
    // do something
  });

  numberOfRulesetChanges(oDataModel).then(function (elements) {
    // do something
  });

  return fireImplicitLock(caseUuid).then(function (lockData) {
    // do something
  }).then(function () {
    // do something
  })
}

Promise.all 就像一扇门,您可以在其中传递一系列承诺,并且只有在所有承诺都解决后才会解决。

let p1 = Promise.resolve(loadLatestDatasetVersion(oDataModel));

let p2 = Promise.resolve(loadCountries(oDataModel));

let p3 = Promise.resolve(numberOfRulesetChanges(oDataModel));

let p4 = Promise.resolve( fireImplicitLock(caseUuid)

let finalPromise = Promise.all([p1,p2,p3,p4]);

finalPromise.then(([datasetVersion,countries,elements,lockData])=>{

    // do something here with datasetVersion, countries, elements, lockData you have all the params cause all the promises are resolved.

})

使用Promise.all 可以实现相同的效果,如上所示。

More about promises

return fireImplicitLock(caseUuid).then(function (lockData) {
    // do something
  }).then(function () {
    // do something
  })

上面的行不会返回任何来自 Promise 的结果,它将返回 Promise object 及其状态 resolved/pending/rejectedvalue

【讨论】:

  • “使用Promise.all 可以达到同样的效果” - fireImplicitLock() 不会等待“以前的”功能之一。为什么 OP 那么应该使用Promise.all()
  • return 语句具有误导性,因为它没有返回任何有用的值。它返回的 Promise 对象。这就是为什么我认为 OP 在不知道它会返回什么的情况下添加了它。是的,你是正确的@Andreas 返回不会等到​​任何承诺解决。
猜你喜欢
  • 2020-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-07
  • 1970-01-01
相关资源
最近更新 更多