My question is about the elegant parallelization of promises in BlueBird when you need to pass both the context and argument to the functions building the promises.
To make my problem understandable and testable, I made an example with no dependency.
Let's suppose I do computation ( 1/(xxx) + 1/(x*x) ) involving an asynchronous "computer" (whose resources must be released). The square and the cube are computed asynchronously and independently.
I can do my computation like this :
InitComputer(2) // returns a promise
.then(invert)
.then(function(arg){
return Promise.all([
proto.square(arg),
proto.cube(arg)
]);
}).spread(function(sq, cu){
this.set(sq + cu);
}).catch(function(err){
console.log('err:', err);
}).finally(endComputer);
But I find this usage of all
too heavy compared to what is theoretically possible. When you pass a function as argument to then
, it's executed. When you pass functions to all
, they're not, there's an error. I suspect I'm missing a utility or pattern...
Is there a solution to change it to something simpler in this style :
InitComputer(2)
.then(invert)
.all([
proto.square,
proto.cube
]).spread(function(sq, cu){
this.set(sq + cu);
}).catch(function(err){
console.log('err:', err);
}).finally(endComputer);
?
I could probably hack Promise.prototype.all or define a new function to avoid increasing the polymorphism but I'm only interested in solutions not involving the modification of objects I don't own.
Annex:
Here's how is defined the "computer" for my test :
var Promise = require("bluebird");
function Computer(){}
function InitComputer(v){
// initializing a computer is asynchronous and may fail hence the promise
var c = new Computer(), resolver = Promise.defer();
setTimeout(function(){
if (v>1) resolver.resolve(v);
else resolver.reject(new Error("bad value: "+v));
},100);
return resolver.promise.bind(c);
}
var proto = Computer.prototype;
proto.square = function(x){
// imagine this really uses the computer and is asynchronous
if (!this instanceof Computer) throw new Error('not a computer');
return x*x
}
proto.cube = function(x){ return x*x*x }
proto.set = function(v){ this.value = v }
function endComputer(){
// releases resources here
console.log('value:', this.value);
}
// this asynchronous function doesn't involve or know the computer
function invert(v){ return 1/v }