2

私の質問は、 Promiseを構築する関数にコンテキストと引数の両方を渡す必要がある場合の、 BlueBirdでの Promise のエレガントな並列化についてです。

私の問題を理解し、テストできるようにするために、依存関係のない例を作成しました。

計算 ( 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 }
4

2 に答える 2