Javascript Promise.all和连续运行Promises之间的区别?

Javascript Promise.all和连续运行Promises之间的区别?,javascript,Javascript,说我有一大堆承诺 const promises = [ /*...*/ ]; 我希望当所有的承诺都解决了的时候会发生一些事情。以下两种方法的区别是什么: 使用Promise.all const allDonePromise = Promise.all(promises); 连续履行承诺 async function allPromises(promisesArray) { const results = []; for (const promise of promisesArra

说我有一大堆承诺

const promises = [ /*...*/ ];
我希望当所有的承诺都解决了的时候会发生一些事情。以下两种方法的区别是什么:

  • 使用
    Promise.all

    const allDonePromise = Promise.all(promises);
    
  • 连续履行承诺

    async function allPromises(promisesArray) {
      const results = [];
    
      for (const promise of promisesArray) {
        results.push(await promise);
      }
    
      return results;
    }
    
    const allDonePromises = allPromises(promises);
    

  • Promise.all
    只是一个做
    allPromises
    所做的事情的内置程序,或者是引擎盖下发生了什么事情来做出承诺。一切都更快。在哪里可以找到有关
    Promise.all
    的内部信息?

    您可以在中找到
    Promise.all
    的规范

    您自己的实现确实在做正确的事情。具体差异如下:

    上述规范在第25.4.4.1.1.r点规定,
    然后
    将在每个承诺上调用。这些调用是同步进行的(注意:不是它们的回调)。无论何时任何承诺得到解决,剩余的承诺都会减少(参见步骤2.10)。每当它变为零时,
    promise.all
    返回的promise将被解析(注意:同步!)

    现在假设你有一个一百万承诺的数组,第一个承诺的解析时间最长,那么你的函数仍然需要执行9999999等待函数返回,而规范中的算法在第一个承诺解析之前已经处理了9999999承诺的解析,在第一个承诺最终解决后,就没有什么可做的了

    例如,您可以在中看到这一点(计数通过递增进行):

    shaka.polyfill.Promise.all=函数(其他){
    var p=new shaka.polyfill.Promise();
    如果(!其他.长度){
    p、 解决([]);
    返回p;
    }
    //结果数组的顺序必须与承诺数组的顺序相同
    //传递给all()。因此我们预先分配数组并记录如何分配
    //许多人已经解决了。只有当所有人都解决了问题时,承诺才会得到回报
    //它自己解决了。
    var计数=0;
    var值=新数组(其他.长度);
    var resolve=函数(p,i,newValue){
    shaka.asserts.assert(p.state_!=shaka.polyfill.Promise.state.RESOLVED);
    //如果数组中的一个承诺被拒绝,则此承诺将被拒绝
    //拒绝和忽略新值。在这种情况下,值数组
    //它的内容在所有承诺兑现之前仍在记忆中
    //在数组中已完成。
    if(p.state==shaka.polyfill.Promise.state.PENDING){
    值[i]=新值;
    计数++;
    if(count==values.length){
    p、 解决问题(价值观);
    }
    }
    };
    var reject=p.reject_uu.bind(p);
    对于(变量i=0;i
    但请注意,浏览器实现是不同的。上面的polyfill只是可能的实现之一

    请注意,您的函数不是“连续运行承诺”。这些承诺正在“运行”*不管你是否对它们做了些什么:它们在你构建它们的时候就完成了它们的工作

    唯一连续化的事情是你开始看(即等待)各自承诺决议的时刻。规范似乎暗示,实现应该从一开始就监听所有承诺的resolve回调。这不能通过循环中的
    wait
    实现(当然,您可以这样做,但是您需要重复调用
    async
    函数,每个承诺调用一次,这将不会给您带来任何使用
    wait
    over
    then
    的好处,因为您需要对
    async
    函数返回的承诺应用
    then

    然后在
    这个
    和参数验证方面还有一些其他(明显的)差异。尤其是ECMA规范说明:

    all
    函数要求其
    this
    值是支持
    Promise
    构造函数参数约定的构造函数



    *承诺不会真正“运行”,因为承诺是对象而不是函数。可能正在运行的是在创建承诺对象时启动的某个异步任务。承诺构造函数回调可能会调用异步API(如
    setTimeout
    fetch
    ,…)这可能会导致异步调用
    resolve
    。最好将此中间状态作为“挂起”(而不是“运行”)的承诺调用。

    相关:相关问题不会询问性能和内部差异。promise.all允许“一次”运行所有承诺-链接承诺以串联方式运行…但是,您的
    allPromises
    函数实际上根本没有链接承诺,因为所有承诺“一次”执行 anyway@JaromandaX承诺执行者不是一调用承诺构造函数就开始运行吗?
    allPromises
    代码不是相当于
    wait promise1;wait promise2;wait promise3;
    这相当于
    promise1。然后(()=>promise2)。然后(()=>promise3);
    shaka.polyfill.Promise.all = function(others) {
      var p = new shaka.polyfill.Promise();
      if (!others.length) {
        p.resolve_([]);
        return p;
      }
      // The array of results must be in the same order as the array of Promises
      // passed to all().  So we pre-allocate the array and keep a count of how
      // many have resolved.  Only when all have resolved is the returned Promise
      // itself resolved.
      var count = 0;
      var values = new Array(others.length);
      var resolve = function(p, i, newValue) {
        shaka.asserts.assert(p.state_ != shaka.polyfill.Promise.State.RESOLVED);
        // If one of the Promises in the array was rejected, this Promise was
        // rejected and new values are ignored.  In such a case, the values array
        // and its contents continue to be alive in memory until all of the Promises
        // in the array have completed.
        if (p.state_ == shaka.polyfill.Promise.State.PENDING) {
          values[i] = newValue;
          count++;
          if (count == values.length) {
            p.resolve_(values);
          }
        }
      };
      var reject = p.reject_.bind(p);
      for (var i = 0; i < others.length; ++i) {
        if (others[i].then) {
          others[i].then(resolve.bind(null, p, i), reject);
        } else {
          resolve(p, i, others[i]);
        }
      }
      return p;
    };