在 javascript 中,returns 承诺并重试内部异步进程最佳实践的函数
In javascript, a function which returns promise and retries the inner async process best practice
我有一个函数,其中 returns 一个 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);
}
}
});
};
最佳做法是避免 promise constructor anti-pattern。基本上,new Promise
主要用于包装非承诺 API,因此如果您的函数已经 return 承诺,那么通常有一种方法可以避免使用它。
如果您的重试次数很少,那么您的情况很简单:
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>
我有一个函数,其中 returns 一个 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);
}
}
});
};
最佳做法是避免 promise constructor anti-pattern。基本上,new Promise
主要用于包装非承诺 API,因此如果您的函数已经 return 承诺,那么通常有一种方法可以避免使用它。
如果您的重试次数很少,那么您的情况很简单:
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>