Мой вопрос об изящном распараллеливании обещаний в BlueBird, когда вам нужно передать как контекст, так и аргумент функциям, строящим обещания.Жидкостная конструкция параллельных обещаний
Чтобы сделать мою проблему понятной и проверяемой, я сделал пример без зависимости.
Предположим, что я выполняю вычисления (1/(x x x) + 1/(x * x)) с использованием асинхронного «компьютера» (ресурсы которого должны быть освобождены). Квадрат и куб вычисляются асинхронно и независимо.
я могу сделать мой расчет, как это:
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);
Но я считаю это использование all
слишком тяжелы по сравнению с тем, что теоретически возможно. Когда вы передаете функцию в качестве аргумента в then
, она выполняется. Когда вы передаете функции all
, это не так, есть ошибка. Я подозреваю, что я пропускаю утилиту или шаблон ...
Есть ли решение, чтобы изменить его к чему-то более простому в этом стиле:
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);
?
Возможно, я мог бы взломать Promise.prototype.all или определить новую функцию, чтобы избежать увеличения полиморфизма, но меня интересуют только решения, не связанные с модификацией объектов, которые у меня нет.
Приложение:
Вот как определил "компьютер" для моего теста:
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 }
Я мог бы получить что-то неправильно, но Арен 't 'proto.square (arg)' и 'proto.cube (arg)' оцениваются немедленно, прежде чем передать их результаты для конструктора массива для 'Promise.all'? (отредактируйте) о, хорошо, они, вероятно, должны быть асинхронными, неважно. – Groo
@Groo Точно. * «Представьте, что это действительно использует компьютер и является асинхронным» *. Я сделал минимальный код, чтобы дать возможность читать вопрос, поэтому мне пришлось взять несколько ярлыков. –