2016-11-03 5 views
6

私は最後の数日間の約束事をしていて、いくつかのプロジェクトを変えようと約束していますが、何回かこの問題を抱えています。

記事やチュートリアル、すべてがスムーズできれいに見える読みながら:しかし、現実には、そのないような約束のあるマルチウェイフローの正しいパターン

getDataFromDB() 
.then(makeCalculatons) 
.then(getDataFromDB) 
.then(serveToClient) 

を。
プログラムは、全体の流れを変える「if条件」をたくさんしている:私は自分自身がthenコールバックにif条件の多くを追加する見つける

  1. getDataFromCache(data).then(function(result){ 
        if(result){ 
         return result; 
        }else{ 
         return getDataFromDB(); 
        } 
    }).then(function(result){ 
        if(result){ 
         serveToClient() //this does not return a promise, so undefined returned... 
        }else{ 
         return getDataFromWebService(); //this does return a promise, 
        } 
    }).then(function(result){ 
        //i dont want to reach here if i already serveToClient()... 
        //so i basically have to check "if(result)" for all next thens 
        if(result){ 
         //do more stuff 
        } 
    }).then(... 
    

    は、私は2つの主要な問題を抱えています。

  2. 私はまだ私は正しいパターンを以下のアム私はすでに


serveToClient)を終了した場合でも、次のthenコールバックに入るのですか?

+0

ノード7で使用できるようになったら、async/awaitを試してください – Endless

答えて

5

論理フローに必要な文は、ifを避けることはできません。 ブランチifの1つの部分で約束を続行したくない場合は、コントロールの流れが必要です。したがって、2番目の.then()ハンドラの一部で、3番目の.then()ハンドラに移動したくない場合は、このようなロジックを分岐して、次の.then()ハンドラを2番目の.then()ハンドラの内側に配置する必要があります。論理。

将来の.then()ロジックをメインチェーンで中止する唯一の方法は、約束を拒否するか(おそらくやりたくない)、別のifのチェックインを追加することですすべて.then()ハンドラがスキップするかどうかを決定する(yuck)。

ので、代わりに、あなたはこのようにロジックを分岐することができます、FYIあなたを

Understanding javascript promises; stacks and chaining

Is there a difference between promise.then.then vs promise.then; promise.then


getDataFromCache().then(function(result){ 
    if(!result) { 
     return getDataFromDB() 
    } else { 
     return result; 
    } 
}).then(function(result){ 
    // branch promise chain here into two separate branches 
    if(result){ 
     // do not continue the promise chain here 
     // call a synchronous operation 
     serveToClient(); 
    } else { 
     // continue promise chain here 
     return getDataFromWebService().then(function(result) { 
      if(result){ 
       //do more stuff 
      } 
     }).then(...); // you can continue the promise chain here 
    } 
}).catch(function(err) { 
    // process any errors here 
}); 

あなたは便利なこれらの他の回答を見つけることができます上記のコードをもう少し協力して再編成することができます

getDataFromCache().then(function(result) { 
    if (result) 
     serveToClient(); 
    } else { 
     return getDataFromWebService().then(function(result) { 
      if(result){ 
       //do more stuff 
      } 
     }).then(...); // you can continue the promise chain here 
    } 
}).catch(function(err) { 
    // process any errors here 
}); 
+0

他の参照回答が追加されました。 – jfriend00

+0

その方法で私の問題は、その後の '.then()'です。 Promiseがコールバックのピラミッドを避けるためのコアな理由の1つではありませんか? – yosiweinreb

+2

@ yosiweinreb - ロジックに必要なレベルのインデントしか必要ありません。厳密な逐次実行の場合は、1つの長鎖しか必要なく、余分なネスティングは必要ありません。 'if'ステートメントでチェーンを分岐させるたびに、1つのレベルの入れ子を追加する必要があります。それについて考えると、同期プログラミングとはまったく違うものではありません。ロジックの残りの部分を継続したくない同期プログラミングで 'if'を追加すると、そこにネストレベルも追加されます。エラー状態を処理する方法を理解し始めると、約束はコールバックよりもはるかに優れています。 – jfriend00

2

他の回答は分岐について説明していますが、「スムーズでクリーン」と尋ねました。

getDataFromCache() 
    .then(result => result || getDataFromDB()) 
    .then(result => result ? serveToClient() : getDataFromWebService() 
    .then(result => { /* Won't reach here if serveToClient */ })) 
    .then(() => { /* can continue promise chain here */ }) 
    .catch(e => console.log(e)); 

お知らせがインデント.thengetDataFromWebService()にあり、末尾に二重の))を参照してください。

あなたはES6 arrow functionsを使用することができます。これは、同期分岐をうまく反映します。あなたはES8 async/await(!Chrome CanaryFirefox Nightlyで利用できるようになりました)を使用することができます

try { 
    if (await getDataFromCache() || await getDataFromDB()) { 
    serveToClient(); 
    } else { 
    let result = await getDataFromWebService(); 
    /* Won't reach here if serveToClient */ 
    } 
    /* can continue here */ 
} catch (e) { 
    // process any errors here 
} 

を、後者は、物事が同期であるかのように、それはasync functions内です提供あなたが完全に制御することができます。

+1

トランスバータを使用しても構わない場合は、本番環境では 'async/await'を使用するのが現実的です(http://babeljs.io/を参照)。 –

関連する問題