【问题标题】:How to update Promise.all with new array?如何用新数组更新 Promise.all?
【发布时间】:2018-01-23 19:12:19
【问题描述】:

在下面的代码中,我想执行abc,但随后是a1,因为a1 被添加到a 中。但是,看起来 Promise.all 并没有更新为添加了新的 a1。最好的方法是什么?有Promise 全部更新吗?我尽量不在a 内做await a1

var arr = [];

async function a() {
  return new Promise(resolve => {
    setTimeout(() => {
    console.log("Resolve a");
    arr.push(a1);
    resolve(1);
    }, 2000);
  });
}

async function b() {
  return new Promise(resolve => {
    setTimeout(() => {
    console.log("Resolve b");
    resolve(2);
    }, 4000);
  });
}

async function c() {
  return new Promise(resolve => {
    setTimeout(() => {
    console.log("Resolve c " + arr.length);
    resolve(3);
    }, 6000);
  });
}

async function a1() {
  return new Promise(resolve => {
    setTimeout(() => {
    console.log("Resolve a1");
    resolve(11);
    }, 2000);
  });
}

arr = [a(), b(), c()];

(async function run() {
  await Promise.all(arr);
})();


console.log('Done');

【问题讨论】:

标签: javascript node.js asynchronous promise es6-promise


【解决方案1】:

首先,你推 a1 我认为你想推 a1() - 否则你推的是一个功能,而不是一个承诺

但这不会改变任何事情,因为传递给 Promise.all 的数组是(在我见过的每个库中)复制的(使用 Array#slice),所以对传入数组的任何更改都不会“可见” " 到 Promise.all(内部)代码

但是,您可以创建一个函数,在数组上递归调用 Promise.all,直到结果的长度等于数组的(当前,新)长度

var recursiveAll = a => Promise.all(a).then(r => r.length == a.length ? r : recursiveAll(a));

var arr = [];

async function a() {
  return new Promise(resolve => {
    setTimeout(() => {
    console.log("Resolve a");
    arr.push(a1());
    resolve(1);
    }, 200);
  });
}

async function b() {
  return new Promise(resolve => {
    setTimeout(() => {
    console.log("Resolve b");
    resolve(2);
    }, 400);
  });
}

async function c() {
  return new Promise(resolve => {
    setTimeout(() => {
    console.log("Resolve c " + arr.length);
    resolve(3);
    }, 600);
  });
}

async function a1() {
  return new Promise(resolve => {
    setTimeout(() => {
    console.log("Resolve a1");
    resolve(11);
    }, 200);
  });
}

arr = [a(), b(), c()];

(async function run() {
  let results = await recursiveAll(arr);
  console.log(results);
})();

【讨论】:

    【解决方案2】:

    有趣的问题...

    你确实可以在运行中修改Promise.all(),用另一个promise替换一个promise,即使新插入的promise解决了最新的。

    在下面的示例中,promise three 将用一个新的 Promise 替换自己,该 Promise 将在 2000 毫秒后解析,Promise.all() 将等到它解析到将其解析值包含到提供给 .then() 的数组中阶段。

    var fun   = _ => new Promise((v,x) => setTimeout(v,2000,5)),
        one   = new Promise((v,x) => setTimeout(v,1000,1)),
        two   = new Promise((v,x) => setTimeout(v,2000,2)),
        three = new Promise((v,x) => setTimeout(v,3000,fun())),
        four  = new Promise((v,x) => setTimeout(v,4000,4));
    Promise.all([one,two,three,four])
           .then(a => console.log(a));  

    请等待 5 秒以查看结果。

    【讨论】:

    • 我想到了这个。但我想要的输出是 [1,2,3,4,5] 其中three() 返回“3”并触发 fun() 返回“5”并添加到列表中。这个列表可以继续下去(我们基本上不知道 fun())。
    • @HP。然后我会说,Promise.all() 必须同步对提供的数组进行排序,其中的项目可以通过异步时间轴中的引用重新分配,而我们不能异步扩展自身(数组参数),因为它已经被处理过。您可能仍然可以对结果进行新的承诺,但我怀疑这些新承诺只能在Promise.all().then() 阶段处理。如果这适合您的用例,我可以稍后展示它。
    • promise three will replace itself with a new promise - 这就是 Promise 的工作原理,解析为 Promise,原来的 Promise “采用”新的 Promise 状态 - Point 2.3.2 of the Promise Resolution procedure
    猜你喜欢
    • 2020-12-12
    • 2019-02-11
    • 1970-01-01
    • 2022-01-08
    • 2013-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-07
    相关资源
    最近更新 更多