Skip to content Skip to sidebar Skip to footer

How Do You Avoid The Promise Constructor Antipattern With Promise.all

How do you avoid the promise constructor antipattern when using multiple promises and Promise.all? Say I have the following code: getFoo = function() { return new Promise(funct

Solution 1:

You can just get rid of new Promise all together.

getFoo = function() {
    var promises = [];
    promises.push(getBar1().then(function(bar1) {
        processBar1(bar1);
        return bar1;
    }));
    promises.push(getBar2().then(function(bar2) {
        processBar2(bar2);
        return bar2;
    }));
    returnPromise.all(promises).spread(function(bar1, bar2) {
        var result = processBothBars(bar1, bar2);
        return result;
    });
}

// start mockfunctiongetBar1() {
    returnPromise.resolve({name:'bar1',processed: false});
}
functiongetBar2() {
    returnPromise.resolve({name:'bar2',processed: false});
}
functionprocessBar1(bar1) {
  bar1.processed = true;
}
functionprocessBar2(bar2) {
  bar2.processed = true;
}
functionprocessBothBars (bar1, bar2) {
  return [bar1, bar2].filter(function (bar) {
    return bar.processed;
  }).map(function (bar) {
    return bar.name;
  });
}
Promise.prototype.spread = function (fn) {
  returnthis.then(function (arr) {
      return fn.apply(this, arr);
  });
};
// end mockvar getFoo = function (fail) {
    var promises = [];
    promises.push(getBar1().then(function (bar1) {
        processBar1(bar1);
        if (fail) {
          throw'getBar1 Failed!';
        }
        return bar1;
    }));
    promises.push(getBar2().then(function (bar2) {
        processBar2(bar2);
        return bar2;
    }));
    returnPromise.all(promises).spread(function (bar1, bar2) {
        var result = processBothBars(bar1, bar2);
        return result;
    });
}
getFoo().then(function (result) {
    console.log(result); // ['bar1', 'bar2']
});
getFoo(true).then(function (result) {
    console.log(result); // doesn't happen
}).catch(function (e) {
    console.error(e); // Error: getBar1 Failed!
});

.then returns a promise, so there's no need to create a new one that wraps it unless you want to prevent errors from reaching the outer promise.

Solution 2:

No need to create any promises of your own here because getBar1() and getBar2() both already return promises - at least we assume so because both are thenable.

Providing processBar1 and processBar2 each returns the result you are interested in, the code will simplify as follows :

var getFoo = function() {
    // write promises as an array literalvar promises = [
        getBar1().then(processBar1),//result returned by getBar1() is automatically passed to processBar1getBar2().then(processBar2) // ... ditto ...
    ];
    returnPromise.all(promises).spread(processBothBars);
};

Solution 3:

Fwiw bluebird proves some sugar over this:

getFoo = function() {
     returnPromise.join(getBar1().tap(processBar1),
                         getBar2().tap(processBar2),
                         processBothBars);
}

Post a Comment for "How Do You Avoid The Promise Constructor Antipattern With Promise.all"