Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular conditional promises

For an angular project, I have to nest promises and I run into cases where I am not sure of what I am doing. Here is one of my code :

return Action1().then(function (data) {
    var defer = $q.defer();
    if (data.condition) {
        $q.all([Action2(), Action3(), Action4()]).then(function () {
            defer.resolve();
        });
    } else {
        defer.reject("error_code");
    }
    return defer.promise;
});

Action1, Action2, Action3 and Action4 are working promises functions. It's a lot of promises and actions depend on conditions. Can I do that and be sure my main function will be always resolved or rejected?

I read that we can pass promise inside resolve function. Can I do that and is this the same as above:

return Action1().then(function (data) {
    var defer = $q.defer();
    if (data.condition) {
        defer.resolve($q.all([Action2(), Action3(), Action4()]);
    } else {
        defer.reject("error_code");
    }
    return defer.promise;
});
like image 283
JeromeModi Avatar asked Apr 16 '15 10:04

JeromeModi


2 Answers

No, it is not. Your first function would stay forever pending if one of Action2(), Action3() or Action4() did "throw", and reject the $q.all(…) promise - your deferred is never resolved then. This is the most common bug of the deferred antipattern you've used here.

Your second function does mitigate this, but is still unncessary complicated. You don't need a deferred here at all! Just return the promise directly, and use $q.reject:

return Action1().then(function (data) {
    if (data.condition) {
        return $q.all([Action2(), Action3(), Action4()]);
    } else {
        return $q.reject("error_code");
    }
});

Or, as this happens inside a then handler, you can also use throw "error_code".

like image 116
Bergi Avatar answered Nov 18 '22 22:11

Bergi


Thanks for your answer, I can see my error on the first code version. I think it's the q.all which perturbs me.

I read the deferred antipattern. It said that we don't have to create deferred objects for no reason.

The simple case is this :

 return Action1().then(function () {
     return $q.all([Action2(),Action3(), Action4()]);           
 });

But due to the if (data.condition) I can't do it. Is my second code the only way to do it? Am I in a case or I have to use defer?

It speaks about "promisification", but with Angular I don't know if it's a good thing (libs seem unmaintained).

Cheers,

like image 32
JeromeModi Avatar answered Nov 18 '22 22:11

JeromeModi