javascript - 那么区 block 不会在链式 promise 中被调用

标签 javascript es6-promise

我正在努力在 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) })

为什么 runPromise(2)runPromise(3)then block 从未被调用?

最佳答案

您的问题是,在 if (promise) 情况下,runPromise 返回的 Promise 永远不会被 res()olved。从执行器回调中返回不会执行任何操作。您可以通过执行以下操作来解决此问题

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 ,这首先导致了这个错误。不要在外部 new Promise 执行器中调用 thennew PromiserunPromise()!而是使用

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) })

关于javascript - 那么区 block 不会在链式 promise 中被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57509387/

相关文章:

javascript - "Non-constructor value passed to NewPromiseCapability"是什么意思?

javascript - 如何在 bulkwrite 的 for 循环中设置异步/等待?

javascript - 性能 - Array.forEach 与实现版本

javascript - 如何组合两个可观察量来创建新的可观察量?

javascript - 预期调用一个断言但收到零个断言调用

javascript - Service Worker Promise.then 未定义

typescript - Angular 2 promise 问题

javascript - 如何在 Xpage 中关闭窗口?

javascript - 如何将(数字)数组加载到谷歌应用程序脚本中 Byte[]

javascript - 更新: Applying AJAX'd JSON data to existing checkboxes and checking/unchecking (jQuery)