【问题标题】:Can I use this implementation of Promise.allSettled before ES2020?我可以在 ES2020 之前使用 Promise.allSettled 的这个实现吗?
【发布时间】:2021-01-15 16:49:25
【问题描述】:

我正在处理一个损坏的代码库,所以我试图尽可能少地接触。特别是,现在它使用的是 TypeScript 和 ES6,我需要启动一系列 Promise 并等待它们全部完成,然后再继续执行代码,无论它们是解决还是拒绝。所以这是 Promise.allSettled 的用例,它只在 ES2020 中可用。

我尝试了以下实现:

const myPromiseAllSettled = (promises) => new Promise((resolve, reject) => {
  const results = []
  const settle = (result) => {
    results.push(result)
    if (results.length === promises.length) {
      (results.every(value => value) ? resolve : reject)(promises)
    }
  }
  promises.forEach(promise => {
    promise
      .then(() => settle(true))
      .catch(() => settle(false))
  })
})

但是我只看到了我自己的关于 Promise 的代码,所以我想获得一些关于我的实现的反馈。它会做其他开发人员期望它做的事情吗?特别是当涉及传递给解决/拒绝的参数时;现在我只传递一系列承诺,并希望开发人员在有兴趣跟进个别承诺时运行.then(promises => promises.forEach(...))

我也不知道如何在这里使用 TypeScript 处理类型,因为我对 TypeScript 也没有那么丰富的经验。 (我觉得到处都写“any”并不酷。)

【问题讨论】:

  • 订单未保存
  • 它不会返回与allSettled 返回的相同的东西(一个通过statusvalue/reason 道具实现对象数组的承诺)它只返回传递给它的内容.
  • 不,这不是一个有效的 polyfill。它不满足或拒绝正确的值。你甚至不需要使用new Promise 构造函数。它应该看起来像 more like thisthat
  • 对我来说,这里的这部分 (results.every(value => value) ? resolve : reject)(promises) 看起来你想要的是 Promise.all 而不是 Promise.allSettled。如果一个人失败了,你还是要扔,那么等待所有人完成有什么意义?为什么不马上扔?为什么resolve/reject 带有一系列承诺? allSettled 会返回一个列表,其中包含哪些承诺成功,哪些承诺失败。这就是为什么它在返回结果之前等待所有完成。

标签: javascript promise


【解决方案1】:

它应该看起来更像这样:

const myPromiseAllSettled = (promises) => {
  const fulfilled = value => ({ status: "fulfilled", value });
  const rejected = reason => ({ status: "rejected", reason });

  return Promise.all([...promises].map(p => Promise.resolve(p).then(fulfilled, rejected)));
}

[...promises] 处理promises 可迭代但不是数组的情况。 Promise.resolve(p) 因为传递的值可能不是 Promise(或 thenable)。

如果您只是想收到有关成功的通知,您可以做一些更简单的事情:

const success = await Promise.all(promises).then(() => true, () => false);

编辑:不喜欢处理promises 的方式可能是一个可迭代但没有数组。在可迭代对象上添加Array#maps 的版本:

function* map(iterable, callback) {
  for (const value of iterable) {
    yield callback(value);
  }
}

const myPromiseAllSettled = (promises) => {
  const fulfilled = value => ({ status: "fulfilled", value });
  const rejected = reason => ({ status: "rejected", reason });

  return Promise.all(
    map(
      promises,
      p => Promise.resolve(p).then(fulfilled, rejected)
    )
  );
}

【讨论】:

  • 你能输入吗?
  • @marzelin 我不明白这个问题,我可以输入什么吗?
  • 我的意思是你能为你的代码提供 TypeScript 类型吗:)
  • @PatrickDaSilva Promise.resolve(p) 是在传递的数组中的值之一是非 thenable 对象(如字符串或数字)的情况下。如果你尝试做"abc".then() 你会得到一个错误。但是,如果您将值包装在 Promise.resolve() 中,一切都会顺利进行(您可以将具有纯值的数组传递给 allSettledPromise.all())。
  • @PatrickDaSilva Promise.resolve(value) 将每个传递的值转换为 Promise,就像 String(value) 将每个传递的值转换为字符串。而关于then的第二个参数,catch(fn)等价于then(null, fn)
猜你喜欢
  • 2010-09-22
  • 2016-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-14
  • 2021-10-24
  • 2021-02-03
相关资源
最近更新 更多