【问题标题】:Promises.all how to ensure all have promises are available?Promises.all 如何确保所有有 promise 都是可用的?
【发布时间】:2018-02-21 20:19:23
【问题描述】:

我从 Axios AJAX 库中获取了这个示例,但 Promises.all() 也是如此。

到目前为止,我已阅读您可以使用Promises.all() 检查是否已解决来自一组承诺的所有承诺。

这确实很简洁,但是如果你推送一个承诺并且它在下一个被推送之前解决,会发生什么?

我猜我的平均 AJAX 调用开销至少为 50 毫秒,推送总是发生在任何 ajax 请求之前,但只是说理所当然的感觉并不正确。

我可以想到两种解决方案:

  1. 使用计数来确保两个(在这种情况下)AJAX 请求都在
    数组。

  2. 检查实际的函数名称。

其他人是如何处理这个问题的,或者大多数人只是满足于希望两个 AJAX 请求都被推送,然后一个请求能够足够快地得到解决。

axios.all([getUserAccount(), getUserPermissions()])
  .then(axios.spread(function (acct, perms) {
    // Both requests are now complete
  }));

【问题讨论】:

  • 不太清楚你在问什么。您是否在动态构建承诺数组?或者您想知道请求是否会在打包之前以某种方式完成?
  • 是的,这些承诺是从多个地方推送的。假设已经推送了一个promise,而我希望有2个promise,那么理论上这个单一promise可能会在第二个promise被推送之前触发一个then?如果是这种情况,是否需要一种机制来事先检查?
  • 您不需要事先检查这一点的机制。 Promise.all 从一系列承诺中做出一个承诺。你是什​​么意思他们被从不同的地方推过来

标签: javascript ajax promise axios


【解决方案1】:

Axios.all calls Promise.all 返回一个单一的 Promise,当可迭代参数中的所有 Promise 都被解决时

Axios.spread 将从getUserAccountgetUserPermission 获取解析值。

【讨论】:

    【解决方案2】:

    push 是同步操作,ajax 是异步的。 JS 将始终在运行任何异步操作之前运行所有同步操作,即使它已经完成。例如:

    for (i=0;i<10000000;i++){
      console.log('looping');
    }
    
    setTimeout(function(){
      console.log('running async')
    }, 0)
    

    虽然timeout设置为0,所以可以立即运行,但会等到for循环完成后才运行异步操作。

    因此,即使您推送了一个 Promise 并且它立即解析,它也会等到推送完成,然后才会对已解析的 Promise 做出反应。

    【讨论】:

    • 哇,我将对此进行测试并阅读它。如果这是真的,那么Promises.all() 是处理多个 AJAX 请求的绝佳解决方案。黄金答案就在那里。
    • 虽然对 async 和 sync 的解释是正确的,但这不是 push 被首先评估的原因:这是因为这是 JavaScript 中正确的评估顺序:一个参数(数组 in这种情况)必须首先在函数(这个参数被传递给它,即Promise.all)被执行(也是同步的)之前被完全评估。所以这和异步代码关系不大。
    【解决方案3】:

    您无需担心在传递给Promise.all 之前解决的承诺:Promise.all 在其(数组)参数被完全评估之前不会被调用。只有当数组准备好时,才会调用Promise.all

    在调用Promise.all 时,这些承诺中的任何一个是否已经解决,实际上并不重要。 Promise.all 将检查哪些处于已解决状态,并且只有在所有这些都已完成时才会调用其 then 方法。甚至可能所有数组中的promise都已经实现了:没问题,只要Promise.all被执行,它就会调度then方法的执行。即使这些承诺已经解决的时间也不重要。即使它们在一小时前得到解决,Promise.all 仍然可以正常工作。

    【讨论】:

    • 我不想检查承诺是否已经解决,因为这些信息是自我包含在承诺中的,实际上Promise.all() 会为我检查这个。我想确保Promises.all() 在我可能没有推送我想要的数组中的所有承诺时不会触发。但是根据@fatman 的回答,pushsync 操作总是会在任何async 请求甚至触发之前发生。所以我想这不再是一个问题。不过感谢您的洞察力,不胜感激。
    • 当您将数组传递给Promise.all 时,您的数组将是完整的。我的观点是,没有办法将不完整的数组传递给Promise.all(当然,除非您故意这样做,并在调用Promise.all 之后修改数组)。 JavaScript 总是在调用传递参数的函数之前先计算参数。
    • 好的,解释器会检查整个代码,并准确知道最后一项何时被推送到该数组中。因此它知道该参数已被完全评估并确保此时仅调用Promise.all?我猜整个async/sync 的故事在这里仍然适用,但在此之前完成的评估?这很难理解,因为我不确切知道解释器如何决定 push 语句何时完成评估。
    • 当您的问题不包含带有push 的代码时,谈论push 有点困难。相反,您有一个包含两个值的数组文字。我的意思是 JavaScript 引擎将首先评估每个数组元素(从左到右),它评估为两个 Promise,然后将这两个值包装到一个数组中,然后调用 Promise.all。这个原则与Promise.all无关。与a = [].concat([1+1, 5-3, 8*2]); 相同:首先进行算术运算,然后使用这些结果创建数组,然后执行concat
    • 是的。在我的代码示例中,我有两个值,但在我的代码库中,这将是一个空数组,组件会将它们的 Promise 推送到其中,因此不会有初始数组元素。我仍然在猜测 javascript 解释了我的整个代码库并且仍然知道所有 push 操作何时完成?
    猜你喜欢
    • 2018-11-14
    • 2021-08-14
    • 2018-02-18
    • 2021-01-07
    • 2019-10-07
    • 2015-04-15
    • 1970-01-01
    • 2023-02-21
    • 1970-01-01
    相关资源
    最近更新 更多