【问题标题】:how to reject promise inside a then如何在 then 中拒绝承诺
【发布时间】:2017-10-25 10:04:29
【问题描述】:

如果任何一个承诺以干净的方式失败,我希望能够拒绝整个承诺链。我想“抓住”这个拒绝并发送错误通知。我已经实现了以下代码:

let reportMetaData = api.ajaxGet(api.buildV3EnterpriseUrl('reports' + '/' + params.report_id))
  .catch(error => {
    if (error.status === constants.HTTP_STATUS.GATEWAY_TIMEOUT) {
      this.notify.error(this.translate('reports.report_timedout'), this.translate('reports.report_timedout_desc'));
    } else {
      this.send('error', error);
    }
  });

let aggregateData = reportMetaData.then(success => {
  try {
    return api.xmlRequest('GET', success.aggregationUrls.elements[0].url);
  } catch (error) {
    return Promise.reject();
  }
}).then(rawData => {
  try {
    return JSON.parse('{' + rawData + '}');
  } catch (error) {
    return Promise.reject();
  }
}, error => Promise.reject(error));

let aggregateReport = aggregateData.then(data => {
  if (!data || !data.report) {
    return Promise.reject();
  }
  return data.report;
}).catch(error =>{ 
    this.notify.error(this.translate('reports.report_timedout'), error); 
});

如您所见,它非常混乱和复杂。有没有办法可以简化这个?如果有人承诺失败,我想要最简单的方法来拒绝整个承诺失败。如何从 then 函数内部执行此操作?此外,似乎抛出的错误一直冒泡到 chrome 控制台作为未捕获的错误。为什么即使我抓住了它也会冒泡?

【问题讨论】:

  • 我错了还是您已经通过 return Promise.reject() 这样做了?我认为你可以简单地留下一些错误捕获器,它会全部转到最后一个......
  • 主要问题似乎是您实际上没有链条。您有几个彼此完全没有关系的单独承诺。您是否打算将所有代码链接到一个承诺链中?您现在的问题无法回答,因为您显然已经知道如何从 .then() 内部拒绝,因为您已经在多个地方这样做了。但是,您必须将所有承诺与Promise.all() 之类的东西一起收集,或者您必须将它们实际链接到一个链中。我们不知道您对代码的用途。
  • 好的。我修改了我的问题。希望现在更清楚了。基本上我想让我的代码更干净。顺便说一句,我确实有承诺链接在一起。例如,aggregateReport 是带有 aggregateData 的“then”,并且 individualReport 也是带有 aggregateData 的“then”。所以,这些是链接在一起的。

标签: javascript ember.js promise es6-promise


【解决方案1】:

您需要使用Promise.all() 并提供promise 数组作为输入参数。 如果其中一个 Promise 失败,则所有 Promise 都不会被解决。 这里是文档:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

这里有一篇关于 SO 的帖子,您可以在其中了解它们:

When to use promise.all()?

【讨论】:

    【解决方案2】:

    尝试聚合 Promise.all(iterable) 下的所有内容。

    更多:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

    如果这不是您想要的,请查看 Bluebird - 功能齐全的 Promise 库。 Here

    更新:如果您想在函数内的任何承诺失败时拒绝整个承诺,请尝试实施:

    throw validationError;
    

    希望它有效。

    【讨论】:

    • OP 没有指定他们使用的是 Bluebird。
    • 是的,我发送它以防万一。不过,第一个链接是 ES6 相关的承诺。
    • 你可能想要明确说明这一点。只是用链接说“使用这个”并不是很有用:)
    • 不使用蓝鸟。我正在使用 ember 承诺。 Promise.all 对我不起作用。我希望能够从 then 函数内部拒绝承诺。所以,我得到了一个结果。我根据某些标准进行验证。如果验证失败,我想拒绝承诺。
    • 也可以在这里查看。我猜几乎相同的问题stackoverflow.com/questions/21260602/…
    【解决方案3】:

    你可以使用异步函数来清理一些东西。我认为您可以用以下代码替换您的代码。

    async function processDataAndReport() {
      try {
        const data = await api.ajaxGet(api.buildV3EnterpriseUrl('reports' + '/' + params.report_id));
        const rawData = await api.xmlRequest('GET', data.aggregationUrls.elements[0].url);
        const { report } = JSON.parse(`{${rawData}}`);                         
      } catch(e) {
        // send notification
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2017-09-04
      • 1970-01-01
      • 1970-01-01
      • 2019-11-25
      • 1970-01-01
      • 2018-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多