【问题标题】:Resolve a promise once all internal concurrent promises have resolved or rejected一旦所有内部并发承诺都已解决或被拒绝,就解决一个承诺
【发布时间】:2015-09-04 23:22:08
【问题描述】:

我正在寻找类似于 Promise.all 的东西,即使在一个或多个 Promise 拒绝或抛出错误的情况下,它也会继续同时解决 Promise。每个请求不依赖于另一个请求。

接近我想要的 - 请看 cmets

function fetchRequest (request) {
  return new Promise(function (resolve, reject) {
    fetch(request)
    .then(function(response) {
      return response.text();      

    }).then(function (responseXML) {
      //Do something here. Maybe add data to dom
      resolve(responseXML);

    }).catch(function (err) {
      reject(new Error(err));
    }
}

function promiseRequests (requests) {
  var result = Promise.resolve();

  for (var i = 0; i < requests.length; i++) {
    result = fetchRequest(requests[i])
  }

  //This is wrong as it will resolve when the last promise in the requests array resolves
  // - not when all requests resolve
  resolve(result);
}

promiseRequests(['url1.com', 'url2.com']).then(function (data) {
  console.log('All requests finished');
  //optionally have data be an array of resolved and rejected promises
});

我已经成功地使用了Promise.all,并且只解决了 fetchRequest 承诺,这导致了预期的结果(结果数组和undefined's),但我觉得这是错误的做事方式.它还消除了我使用抛出错误的能力。

有效,但感觉使用 resolve 不正确

function fetchRequest (request) {
  return new Promise(function (resolve, reject) {
    fetch(request)
    .then(function(response) {
      return response.text();      

    }).then(function (responseXML) {
      resolve(responseXML);

    }).catch(function (err) {
      resolve();
    }
}

Promise.all([fetchRequest('url1.com'), fetchRequest('url2.com')]).then(function (data) {
  console.log('All requests finished', data); //data could be ['resultXML', undefined]
});

请仅使用原生 es6 Promise API 回答谢谢。

【问题讨论】:

  • "它还消除了我使用抛出错误的能力。" - 那么为什么不只是resolve(err)?你打算如何使用它们?您想如何区分履行和拒绝?
  • 啊,我明白了。在阅读了您的链接 Bergi 之后,我认为我对承诺的理解终于得到了点击。我认为 Domenic 的回答解决了我的问题的症状,但 Bergi 的回答解决了根本原因。

标签: javascript promise es6-promise


【解决方案1】:

我已经成功地使用了Promise.all 并且只解决了fetchRequest 承诺

这基本上是要走的路。对于这种情况,ES6 没有像 allSettled (Q) 或 settle (Bluebird 2.x) 这样的辅助函数,所以我们需要像你一样使用 Promise.all。 Bluebird 甚至为此提供了专用的 .reflect() 实用程序。

但是,在被拒绝的情况下,您不会使用 undefined 来解决它们,而是使用一些可以识别错误的有用值。

function promiseRequests(requests) {
  return Promise.all(requests.map(request => {
    return fetch(request).then(res => {
      return {value:res};
    }, err => {
      return {reason:err};
    });
  }));
}

【讨论】:

  • )) 结束于Promise.all() 。问题:此模式是否处理 taoofcode.net/promise-anti-patterns 中描述的“过度敏感的错误处理程序”案例?
  • @guest271314:无需“处理”它 - this usage is not an antipattern(是的,我知道我在做什么 :-)
  • 注意,如果在 .map() 内没有 return ,在 fetchpromiseRequests 似乎返回 undefined for Promisejsfiddle.net/gn81Lf6u/2jsfiddle.net/gn81Lf6u/3
  • @guest271314:这是一个箭头函数,其中返回是隐式的 :-) 但为了清楚起见,我已经进行了编辑(以及与其他两个表达式的一致性,其中不可能有简洁的主体)
  • "这是一个箭头函数,返回是隐式的 :-)" 在没有 return 之前在 fetch 之前尝试了每晚的箭头函数;似乎返回 undefinedPromise 值来自 promiseRequests jsfiddle.net/gn81Lf6u/5jsfiddle.net/gn81Lf6u/7
【解决方案2】:

您本质上是在寻求一种方法来消除任何错误。因此,像这样的函数将是您最好的选择:

function swallow(p) {
  // transforms rejected promises into promises fulfilled with undefined
  return p.catch(function () { });
}

您可以按如下方式使用它:

Promise.all([swallow(fetch('url1.com')), swallow(fetch('url2.com'))]).then(function (data) {
  console.log('All requests finished', data); //data could be ['resultXML', undefined]
});

甚至

 const promises = ['url1.com', 'url2.com'].map(fetch).map(swallow);
 Promise.all(promises).then(function (data) {
   // ...
 });

【讨论】:

    猜你喜欢
    • 2018-04-02
    • 2017-06-13
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 2015-06-24
    • 2022-11-22
    • 1970-01-01
    • 2013-06-22
    相关资源
    最近更新 更多