【问题标题】:How to Retry a Promise in ES6 [duplicate]如何在 ES6 中重试 Promise [重复]
【发布时间】:2017-01-18 23:12:06
【问题描述】:

我一直在尝试找出如何最好地实现重试,例如使用 Promise 下载失败。我最好的猜测是用一个新的 Promise 来解决一个 Promise(见下面的伪代码),但我在文档中只能找到 Promise.resolve() 可以用 thenable 调用(所以,我相信,用 Promise )。这是否也适用于 promise 构造函数中的解析回调?我的方法是正确的还是有更好的方法来实现重试?

function getdata(url) {
   return new Promise(function(resolve, reject) {
      ajaxcall({
         url: url,
         success: function(data) { resolve(data); },
         failure: function(err) { 
            if(retriable(err)) {
               resolve(getdata(url));
            }
            else {
               reject(err);
            }
         }
      });
   });
}

【问题讨论】:

  • 这很容易找到:new Promise(resolve => resolve(Promise.resolve(42))).then(v => console.log(v)); 记录42,而不是承诺。所以是的,它似乎也适用于resolve
  • 通用承诺重试助手var retry = fn => _ => fn().catch(retry(fn));
  • 通用限制承诺重试次数var retryP = (fn, retry) => fn().catch(err => retry > 0 ? retryP(fn, retry - 1) : Promise.reject(err));

标签: javascript node.js ecmascript-6 promise es6-promise


【解决方案1】:

你的方法会奏效。当一个 Promise 被传递给 Promise 构造函数的 resolve 回调时,该 Promise 的解析值被用作“外部”promise 的解析值。

ajaxcall 包装在一个返回承诺的函数中可能会更简洁,这样您就不会混合和匹配承诺和回调范式。

function fetch(url) {
  return new Promise(function(resolve, reject) {
    ajaxcall({
      url: url,
      success: resolve,
      failure: reject
    });
  });
}

function getdata(url) {
  return fetch(url)
    .catch(function(err) {
      if(retriable(err)) {
        return getdata(url); // or fetch(url) to retry only once
      } else {
        throw err;
      }
    });
}

【讨论】:

  • 请注意,根据现代规则,这可能会被标记为错误代码,因为内部 fetch 没有错误处理,并且鼓励 JS 引擎禁止让错误消失在空白中的承诺。你可以再次返回getdata(url),而不是fetch(url)
  • @Mike'Pomax'Kamermans 您能否详细说明或指出提及此规则的资源?谁来做“标记”?短绒?
  • 引擎本身。例如,Node.js 当前使用的 V8 版本,当告诉他们运行 new Promise(function(resolve, reject) { throw new Error('test'); }) 时会警告 UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: test。在这种特殊情况下:通过调用fetch 而不是getdata,我们失去了“查看”(并处理)与初始故障无关的错误的能力(例如,硬件故障导致网络错误第二次尝试)
  • 但是,在上述情况下,添加.catch() 处理程序不是getdata() 的调用者的责任吗?如果getdata() 的调用者没有捕捉到最终错误,您的建议将如何缓解问题?
  • 当然,但是 getdata 已经有代码来处理重试,利用它并​​确保retriable(err) 在需要重试的情况下多次执行正确的操作比“重试一次,仅一次”构建。您的建议不错,但只需稍加改动即可使其变得更好。
【解决方案2】:

您可以更改代码以在 Promise 中调用内部函数。像这样的:

function getdata(url) {
   return new Promise(function(resolve, reject) {
    function call() {
     return ajaxcall({
          url: url,
          success: function(data) { resolve(data); },
          failure: function(err) { 
             if(retriable(err)) {
                call();
             }
             else {
                reject(err);
             }
          }
       });
     }
     call(); 
   });
}

【讨论】:

    猜你喜欢
    • 2016-05-22
    • 1970-01-01
    • 2023-03-20
    • 2016-12-12
    • 2016-12-20
    • 1970-01-01
    • 2018-07-09
    相关资源
    最近更新 更多