在javascript中,一个返回promise并重试内部异步进程最佳实践的函数

时间:2015-07-24 14:13:55

标签: asynchronous promise es6-promise

我有一个返回javascript Promise的函数,在其中运行一些异步代码。异步代码需要在失败的情况下重试几次。 我这样做,直到我观察到一些奇怪的行为让我想知道我是否正确行事。所以我不得不改变它。这两种方法都在这里。 我知道为什么第一种方法(asyncFunc)不起作用,如果有人可以分享一些技术清晰度,我将不胜感激。 对于第二种方法(ayncFunc_newer),有关如何更好地完成任何建议吗?



var _retryCount = 0;

// this is what I was doing
function asyncFunc () {
	return new Promise(function(fulfill, reject) {
		doAsync()
			.then(fulfill)
			.catch(retry);

		function retry(promiseResult) {
			if(_retryCount < 3) {
				_retryCount++;
				return asyncFunc();
			}
			else {
				reject(promiseResult);
			}
		}
	});
}

// this what I'm doing now
function ayncFunc_newer() {
    return new Promise(function(fulfill, reject) {
        var retryCount = 0;

        doAsync()
            .then(fulfill)
            .catch(onReject);

        function onReject(bmAuthError) {
            if(retryCount < 3) {
                retryCount++;
                logWarning(error);
                
                doAsync()
                	.then(fulfill)
                	.catch(onReject);
            }
            else {
                fulfill(false);
            }
        }
    });                 
};
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:9)

最佳做法是避免使用promise constructor anti-pattern。基本上,new Promise主要用于包装非承诺API,因此如果您的函数已经返回promise,那么通常有一种方法可以避免使用它。

如果您正在进行较低的固定次数重试,那么您的情况就像:

一样简单
function ayncFunc() {
  return doAsync().catch(doAsync).catch(doAsync).catch(doAsync);
};

对于可配置的重试次数,您可以将其扩展为:

var retries = 3;

function ayncFunc() {
  var p = doAsync();
  for (var i = 0; i < retries; i++) {
    p = p.catch(doAsync);
  }
  return p;
};

或者,对于更高的重试次数,您可以使用递归方法:

function ayncFunc() {
  function recurse(i) {
    return doAsync().catch(function(e) {
      if (i < retries) {
        return recurse(++i);
      }
      throw e;
    });
  }
  return recurse(0);
};

var console = { log: msg => div.innerHTML += msg + "<br>" };

function doAsync() {
  console.log("doAsync");
  return Promise.reject("Nope");
}

function ayncFunc() {
  return doAsync().catch(doAsync).catch(doAsync).catch(doAsync);
};

var retries = 3;

function ayncFunc2() {
  var p = doAsync();

  for (var i=0; i < retries; i++) {
    p = p.catch(doAsync);
  }
  return p;
};

function ayncFunc3() {
  function recurse(i) {
    return doAsync().catch(function(e) {
      if (i < retries) {
        return recurse(++i);
      }
      throw e;
    });
  }
  return recurse(0);
};

ayncFunc().catch(function(e) { console.log(e); })
.then(ayncFunc2).catch(function(e) { console.log(e); })
.then(ayncFunc3).catch(function(e) { console.log(e); });
<div id="div"></div>