2016-11-25 10 views
5

私のコードでは、条件付きタスクがあり、すべてが約束を返します。タスクを順番に実行する必要があります。複数の条件付き約束をチェーンするにはどうすればいいですか?

私の現在の実装では、このようなものになります。

var chain = []; 

if (/* some condition for task A */) { 
    chain.push(function(doContinue){ 
     taskA().then(doContinue); 
    }); 
} 

if (/* some condition for task B */) { 
    chain.push(function(doContinue){ 
     taskB().then(doContinue); 
    }); 
} 

if (/* some condition for task C */) { 
    chain.push(function(doContinue){ 
     taskC().then(doContinue); 
    }); 
} 

var processChain = function() { 
    if (chain.length) { 
     chain.shift()(processChain); 
    } else { 
     console.log("all tasks done"); 
    } 
}; 

processChain(); 

これはうまく動作しますが、最初に私は約束を使用して.thenを使用して、すべての機能を連鎖チェーンを作成する方法を探していましたが、私はありませんでした実用的な解決策を得ることができます。

thenコールの約束とチェーンのみを使用するクリーナーの方法がある場合は、例を参照してください。

+0

条件を非同期的に評価する必要がありますか(前回の約束ステップの後)、または単に同期させるだけですか? – Bergi

+0

@Bergi条件は最初に評価することができ、約束によって生成された結果には依存しません。 – bummzack

+0

その後、raina77owsソリューションが最適です。 – Bergi

答えて

9

一つの可能​​なアプローチ:

var promiseChain = Promise.resolve(); 
if (shouldAddA) promiseChain = promiseChain.then(taskA); 
if (shouldAddB) promiseChain = promiseChain.then(taskB); 
if (shouldAddC) promiseChain = promiseChain.then(taskC); 
return promiseChain; 

もう1:

return Promise.resolve() 
    .then(shouldAddA && taskA) 
    .then(shouldAddB && taskB) 
    .then(shouldAddC && taskC); 
+2

これらの2つのアプローチは完全に同等ではないことを指摘しておきます。 アプローチ1では、各 '.then()'は連鎖されないか連鎖されています。 アプローチ2では、各 '.then()'は無条件に連鎖し、成功ハンドラを持っているか持っていません。 ハンドラがなくても、チェーン化された '.then()'はすべて下流の遅延を導入するため、アプローチ2はアプローチ1と比較して失敗したテストごとに追加のダウンストリーム遅延を導入します。 –

+0

多くの場合、問題。 遅延の大きさのオーダー(jsFiddleのネイティブプロミスをOpera 1.4.0で使用した1.4GHz Netbook上)は、10000 '.then(null)'あたり約1秒です。 違いが現れる最も可能性の高いシナリオは、構築されたチェーンに対していくつかの他の約束が争っているところです。アプローチ2は、アプローチ1と比較してレースを失う可能性が高くなります。 –

1

あなたはこのことについての素晴らしい何async/await新しい構文

async function foo() { 
    let a = await taskA() 
    if (a > 5) return a // some condition, value 

    let b = await taskB() 
    if (b === 0) return [a,b] // some condition, value 

    let c = await taskC() 
    if (c < 0) return "c is negative" // some condition, value 

    return "otherwise this" 
} 

foo().then(result => console.log(result)) 

を使用することができている - 脇からコードが非常にフラットで読みやすい(imo) - 値a,b、およびcは、すべて同じスコープで使用できます。つまり、条件と戻り値は、タスクの約束した値の任意の組み合わせに依存する可能性があります。

+0

あなたの例は、参考になりますが、元の質問とは少し異なるシナリオです。問題は、非同期操作を条件付き(またはスキップ)する方法でしたが、あなたは常に上から順に実行され、2番目または3番目の操作を条件付きで実行します。 – BeniRose

+0

@BeniRose私はあなたが何を意味しているのかは不明です。例えば、 'a> 5 'の場合、' taskB'と 'taskC'のどちらも実行されません - 非同期操作は事実上条件付きでスキップされます。 'taskA'が何らかの外部条件によって制御されることを意図されているなら、それも良いことです。この答えは、 'async' /' await'が本質的に同期コードと非同期コードの間の線をぼかすことを可能にすることを示しています。 – naomik

+0

*「async」/「await」の仕組みを理解すると、*「チェーンの複数の条件付き約束」*というこの質問は消えます。 - 質問者の心は、「鎖」*や「約束」*問題は*「複数の条件をどのように順序づけるか?これは簡単な答えがあります: 'if ...'/'else if ...'/'else ...' – naomik

関連する問題