user2738707
user2738707

Reputation: 125

Resolving from the middle of a promise chain

In my code, I'm using the Q library to chain multiple API calls like so:

function long_promise_chain() {
    var q = Q.defer();
    call_api_batch1()
        .then(function(v) {
            if (v.bar) {
                q.resolve();
            } else {
                return call_api_batch_2();
            }
        })
        .then(function(v) {
            if (v.bar) {
                q.resolve();
            } else {
                return call_api_batch_3();
            }
        })
        .then(function(v) {
            if (v.bar) {
                q.resolve();
            } else {
                return call_api_batch_3();
            }
        }, function(err) {
            console.log("err: " + err);
        });
    return q.promise
}

I am seeing that even if the chain is resolved after the first batch the next then block is getting run and causing an error - trying to access an undefined variable and then calling the function(err) block.

Can you please suggest the right way to resolve early.

Update: The issue is that if the the first q.resolve() is called, I don't want the next .then in the chain to triggered. While the q.resolve is called correctly and returns control to the caller, there is an error being printed because, in the second then, there is no 'v' and the error is 'Cannot Read property bar of undefined' when testing v.bar.

Upvotes: 2

Views: 905

Answers (2)

just.another.programmer
just.another.programmer

Reputation: 8785

There's two separate resolve's to deal with in your case.

  1. First the lower case q which holds a deferred object. This is the promise which you return from long_promise_chain.
  2. Second, the promise at each stage of you chain. Ie, the promise returned from each then call in the chain to the subsequent then.

You resolve or reject q by calling the method on q directly. You can resolve or reject the then promise by returning Q.resolve() or Q.reject() from the then block.

Here's a sample:

favorite In my code, I'm using the Q library to chain multiple API calls like so:

function long_promise_chain() {
    var q = Q.defer();
    call_api_batch1()
        .then(function(v) {
            if (condition) {
                q.resolve();
                return Q.reject();
            } else {
                return call_api_batch_2();
            }
        })
        .then(function(v) {
            if (condition) {
                q.resolve();
                return Q.reject();
            } else {
                return call_api_batch_3();
            }
        })
        .then(function(v) {
            if (condition) {
                q.resolve();
                return Q.reject();
            } else {
                return call_api_batch_3();
            }
        }, function(err) {
            console.log("err: " + err);
        });
    return q.promise
}

Upvotes: 0

BaldEagle
BaldEagle

Reputation: 1018

I hope I understand you. Is this what you want?:

function long_promise_chain() {
    var q = Q.defer();
    var allDone = false;
    call_api_batch1()
        .then(function(v) {
            if (v.bar) {
                q.resolve();
                allDone = true;
            } else {
                return call_api_batch_2();
            }
        })
        .then(function(v) {
            if (!allDone) {
                if (v.bar) {
                    q.resolve();
                    allDone = true;
                } else {
                    return call_api_batch_3();
                }
            }
        })
        .then(function(v) {
            if (!allDone) {
                if (v.bar) {
                    q.resolve();
                    allDone = true;
                } else {
                    return call_api_batch_3();
                }
            }
        }, function(err) {
            console.log("err: " + err);
        });
    return q.promise
}

Upvotes: 1

Related Questions