chaining recursive promise with bluebird

2020-03-18 05:13发布

问题:

I have a promise chain with a recursive promise doAsyncRecursive() in the middle like so:

doAsync().then(function() {
    return doAsyncRecursive();
}).then(function() {
    return doSomethingElseAsync();
}).then(function(result) {
    console.log(result);
}).catch(errorHandler);

doAsyncRecursive() has to do something and if it at first does not succeed, i then after want to try every 5 seconds until it does. This is what my promise function looks like:

function doAsyncRecursive() {
    return new Promise(function(resolve, reject) {
        //do async thing
        if (success) {
            resolve();
        } else {
            return new Promise(function(resolve, reject) {
                setTimeout(function() {
                    doAsyncRecursive();
                }, 5000);
            });
        }
    });
}

But when I execute, the chain does not continue after doAsyncRecursive() is successful on the 2nd try and resolve() is called (it continues if the attempt is successful on the 1st try however).

What pattern do I need to make this work?

回答1:

Catch the failure, wait five seconds, then try again.

function doAsyncRecursive() {
    return doAsyncThing().catch(function() {
        return Promise.delay(5000).then(doAsyncRecursive);
    });
}

Here doAsyncThing is a function corresponding to the //do async thing comment in the OP's code, defined as returning a promise. In the original code, the success or failure of the "do async thing" is tested using a success flag, but by definition asynchronous routines do not deliver such a flag; they deliver their results either via a callback or a promise. The code above assumes that doAsyncThing returns a promise. It also assumes that "failure", in the sense of "does not return the response i want", is represented by that promise rejecting. If instead "success" or "failure" is to be defined as some particular value of a fulfilled promise, then you'd want to do

function doAsyncRecursive() {
    return doAsyncThing().then(function(success) {
        if (success) return success;
        else return Promise.delay(5000).then(doAsyncRecursive);
    });
}