【问题标题】:Capture when the last promise resolves in a recursive promise捕获最后一个 Promise 在递归 Promise 中解决的时间
【发布时间】:2019-02-01 01:32:01
【问题描述】:

我正在调用一个函数,该函数本质上返回一个用列表或什么都解决的承诺。然后我为列表中的每个项目调用相同的函数。最终,一切都将一无所有。我只想在所有代码都解决后才运行一些代码,但不知道该怎么做。

为了简化我的问题,我创建了这个示例。我只能控制递归函数。将所有的 Promise 保存到一个数组中,并将其传递给 Promises.all() 示例如下:

function randomLowerInt(int) {
  return parseInt(Math.random() * int);
}

function smallerArray(size) {
  const arr = [];
  const smallerSize = randomLowerInt(size);
  for (let i = 0; i < smallerSize; i++) {
    arr.push(i);
  }
  return arr;
}

function createPromise(arrLength) {
  const secnds = parseInt(Math.random() * 20) * 1000;
  const timeCreated = new Date().getTime();
  const p = new Promise(res => {
    setTimeout(() => {
      const timeResolved = new Date().getTime();
      res({
        timeCreated,
        timeResolved,
        arrLength
      });
    }, secnds);
  });
  return p;
}

function recursive(arr) {
  arr.forEach(() => {
    createPromise(arr.length).then(({
      timeCreated,
      timeResolved,
      arrLength
    }) => {
//      console.log({
//        timeCreated,
//        timeResolved
//      });
      const smallerArr = smallerArray(arrLength);
      recursive(smallerArr);
    });
  });
}
recursive([1, 2, 3, 4, 5]);

const promises = [];

function recursive2(arr) {
  arr.forEach(() => {
    const p = createPromise(arr.length).then(({
      timeCreated,
      timeResolved,
      arrLength
    }) => {
      const smallerArr = smallerArray(arrLength);
      recursive2(smallerArr);
      return ({
        timeCreated,
        timeResolved
      });
    });
    promises.push(p);
  });
}
recursive2([1, 2, 3, 4, 5]);
console.log('Waiting...');
Promise.all(promises).then(vals => console.log(vals));

不起作用,因为Promise.all() 将在数组完全填充之前被调用。

【问题讨论】:

  • recursive2(smallerArr).forEach() 中的预期结果是什么?在哪个递归调用中arr 不是数组?
  • 承诺的全部意义不在于拥抱 JS 的异步特性吗?我的意思是你可以返回 Promises(一旦解决就会变成值),这允许你的程序在这些 Promise 等待它们的返回值时评估 unblocked。控制台记录这些值,它捕获了 console.log 点的值状态,实际上并不能帮助您了解承诺正在解决什么,因为它们不会等待任何值,就像运行时等待任何底层不完整异步操作。有用的帖子:blog.domenic.me/youre-missing-the-point-of-promises
  • vals.then() 链接到Promise.all() 的预期结果是什么?
  • @jaredgorski - 所有的优点。但是,有些用例会驱动多个同时进行的异步操作,这些操作最终会形成最终用户需要的信息架构。一个例子可能是使用微服务或 FAAS 类型系统。在这种情况下,OP 有一个很好的问题。
  • 顺便说一句,这推动了 JavaScript 语言中 async/await 的采用。

标签: javascript promise


【解决方案1】:

如果预期结果只有单个对象中的timeCreatedtimeResolved 属性,您可以将数组声明为变量,.push() 数组的值return @ 987654325@ 来自.map() 而不是.forEach(),并将结果记录在链接的.then() 中。

该模式可以用.reduce()async/await 替换为for..of 循环或其他模式。

let res = []
function recursive(arr) {
  return arr.map((promise) => {
    return createPromise(arr.length).then(({ timeCreated, timeResolved, arrLength }) => {
      console.log({ timeCreated, timeResolved });
      res.push({ timeCreated, timeResolved });
      const smallerArr = smallerArray(arrLength);
      return Promise.all(recursive(smallerArr));
    });
  });
}

Promise.all(recursive([1, 2, 3, 4, 5])).then(() => console.log(res));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-09
    • 2023-03-31
    • 2018-01-24
    • 1970-01-01
    • 2020-01-11
    • 2019-08-03
    • 1970-01-01
    相关资源
    最近更新 更多