5

プロミスの解決された値を返す関数を求めています。正常に失敗することは間違いなくおまけですが、関数が呼び出されたときに promise が解決される準備ができていることが想定された前提条件です。

以下のようなキュー操作を可能にするwebdriver.js promise 実装を使用していますが、キュー/チェーンなどのセマンティクスであまり迷子になりたくありません。達成しようとしています:

var inputs = [...], outputs;
outputs = inputs.map(function(input){
  //queue some async tasks to be performed with input
  queue.enqueue(...);
  //I can't return the *output* value here yet, naturally, so instead
  return promise;
});

//now I'll add another task to the same queue
//this means that by the time this task is run
//the async tasks above would have been executed
//and the promises would be "resolvable"... right?
queue.enqueue(function(){
  console.log(outputs); //>an array of promises
  console.log(doSomeMagic(outputs)); //>resolved values as needed <<<
});

NB: afaikQ.all()は私が求めていることを実行しません。promise の配列を取り、解決された valueではなく、配列の promise を返します。私は間違っていることが証明されてうれしいです。

4

3 に答える 3

4

promise の最終的な値を取得する唯一の方法は、 を使用することthenです。関数が非同期で作業を実行する場合、promise を返す必要があり、いかなる状況でもプレーンな値を返すことはできません。そのためには、作業が完了するまでスレッドの実行を必ずブロックする必要があります。これは、デッドロックやインターリーブの危険性を伴うスレッドまたはファイバーでのみ可能です。

そのため、最終的な値を取得するためにフォローアップすることを除いて、実際には必要な方法ですQ.all then

Q.all(inputs.map(function (input) {
   return promiseForOutput; // however you go about this 
}))
.then(function (outputs) {
   // at this event, outputs is an array of output values
});

もちろん騙す方法はあります。準備ができているか、失敗したか、まだ準備ができていないかpromise.inspect()など、promise の状態を説明するオブジェクトを返します。あなたが言うように、によって返された約束が満たされていることが保証されている場合、これを行うことができます:{state: "fulfilled", value: value}{state: "rejected", error}{state: "pending"}outputsQ.all

outputs = outputs.inspect().value

これはお勧めしません。promise が解決されたことを知る最良の方法は、 を使用することthenです。

また、何らかの外部手段を通じてoutputsすべての準備が整っていることを保証できる場合は、作成した配列に値をプッシュすることもできます。outputs

var endResult = Q.defer();

var outputs = [];
inputs.forEach(function (input) {
    outputPromise.then(function (output) {
        outputs.push(output);
        check();
    }, endResult.reject);
});
check();

function check() {
    if (outputs.length === inputs.length) {
        // manipulate outputs directly, they are ready
        endResult.resolve();
    }
}

return endResult.promise;

ただし、最善の方法は、Q.all(outputs).thenすべての出力の準備が整った後に発生することが保証されているイベントを取得するために使用することです。

于 2013-08-30T23:29:02.243 に答える
3

一般に、Promise が解決されるかどうかはわからないため、単純にそれらを単純な値に変換することはできません。Q.all非同期コンテキストから値配列を抽出できないため、promise を返さなければなりません。Promise に値があることを知っているのは成功ハンドラーだけであり、とにかく値を取得しています。promise がいつ解決したかを知らせる別のイベント システムを使用しないでください。promise 自体を使用してください。

したがって、を使用する代わりにqueue.enqueue、単に置くだけQ.all(outputs).then(function(values){ /* do something */ })です。ただし、それを回避できない場合は、Promiseのinspectデバッグ方法を参照してください_.pluck(_.invoke(outputs, "inspect"), "value")。ただし、値を promise に保存しない方が簡単な場合があることに注意してください。

于 2013-08-30T10:22:46.193 に答える