我正在尝试重试JS中的一些异步调用。当简化并重写为setTimeout
时,逻辑如下所示:
let error = true
let promise = null
const runPromise = (value) => new Promise((res) => {
if (!error) {
res()
return
}
if (promise) {
return promise.then(() => {
return runPromise(value)
})
}
promise = new Promise((res2) => {
setTimeout(() => {
promise = null
console.log(value)
error = false
res2()
}, 1000)
}).then(() => res())
})
runPromise(1).then(() => { console.log(1) })
runPromise(2).then(() => { console.log(2) })
runPromise(3).then(() => { console.log(3) })
为什么从来没有调用
then
和runPromise(2)
的runPromise(3)
块? 最佳答案
您的问题是在if (promise)
情况下,runPromise
返回的承诺永远不会被res()
兑现。从执行程序回调中return
执行任何操作。您可以通过执行此操作来解决此问题
const runPromise = (value) => new Promise((res) => {
if (!error) {
console.log("resolve immediately without error")
res()
} else if (promise) {
promise.then(() => {
console.log("resolve after waiting for previous promise")
res(runPromise(value))
})
} else {
promise = new Promise((res2) => {
setTimeout(() => {
promise = null
error = false
res2()
console.log("resolve after timeout")
res()
}, 1000)
})
}
})
但实际上您应该避免使用
Promise
constructor antipattern,它首先会导致此错误。不要在外部then
执行器中调用new Promise
,runPromise()
或new Promise
!改为使用let error = true
let promise = null
function runPromise(value) {
if (!error) {
console.log(value, "resolve immediately without error")
return Promise.resolve();
} else if (promise) {
console.log(value, "defer until promise")
// now this `return` works as expected
return promise.then(() => {
console.log(value, "trying again")
return runPromise(value)
})
} else {
console.log(value, "starting timeout")
promise = new Promise(res2 => {
setTimeout(res2, 1000)
}).then(() => {
promise = null
error = false
console.log(value, "waited for timeout")
});
return promise;
}
}
runPromise(1).then(() => { console.log(1) })
runPromise(2).then(() => { console.log(2) })
runPromise(3).then(() => { console.log(3) })