2016-05-08 9 views
1

新しいゲームを作成するためにサーバー上で投稿リクエストを受け取ると、私は2つのクエリを実行します。まず、ユーザーが既にゲームに参加しているかどうかを検索し、そうであればゲームを返します。さもなければ、誰かが相手を待っているオープンなゲームを探してそのゲームを返します。最後に、上記の状態のゲームが見つからない場合は、新しいゲームを作成して返します。だから私のコードは次のようなものになります。ExpressJS/NodeJS/Promises:約束のチェーンから早めに返信

.post(function(req, res, next){ 

    ...findUsersExistingGame... 

    .then(function(game){ 
    if(game){ return res.send(game); } 
    else{ 
     return ...findUserWaitingForOpponentsGame... 
    } 
    } 
    .then(function(game){ 
    if(game){ return res.send(game); } 
    else{ 
     return ...createNewGame... 
    } 
    }) 
    .then(function(game){ 
     return res.send(game); 
    }) 
    .catch(function(err){ 
     return next(err); 
    }); 

を私は最終的には読みやすくするためのヘルパー関数に各機能をリファクタリングしますが、私は最初のチェーンを把握する必要があります。私の質問は、私が約束のチェーンの早い段階でゲームを見つけた場合(つまり、ユーザーの既存のゲームか、相手を待っている別のユーザーがいる場合)、私はres.send(ゲーム)を返します。しかし、私の前の.then()ステートメントが未定義を返したため、3番目の。私がres.send(ゲーム)をしたい場合、私は約束のチェーンから早めに戻っていかなければなりませんか?

オプション1:私はエラーをスローして明示的にキャッチする提案を見たことがありますが、それはエラーを使用してフローを制御することは根本的に間違っています。

オプション2:代わりに約束をチェーンで、私はこのような何かを行うことができますが、これは「約束/コールバック地獄」に似:私はまだしようとしているので、

.post(function(req, res, next){ 

    ...findUsersExistingGame... 

    .then(function(game){ 
    if(game){ return res.send(game); } 
    else{ 
     ...findUserWaitingForOpponentsGame... 
     .then(function(game){ 
      if(game){ return res.send(game); } 
      else{ 
       return ...createNewGame... 
       .then(function(game){ 
        return res.send(game); 
       }); 
      } 
     }) 
    } 
    } 

(好ましくはES5であり、別の方法であります基本的に約束を理解することができますが、ES6も歓迎です)ここ

+0

ES7の提案されているasync/await構文(https://github.com/yortus/asyncawait#1-introduction)を探しているような感じです。あなたが今それをしたい場合は、おそらくそれのためのtranspilerを見つけることができます... –

+0

コールバック地獄/投げているエラーは私の唯一のオプションですか? – PDN

+0

@PDN「yield」と(ES6)はどうですか?または 'イベント駆動アーキテクチャ'? –

答えて

5

主な問題は、あなたが道に沿って各ステップからの三つの可能な戻り値を持っていることです。

  1. ゲームは、ゲーム
を探しながら
  • ゲームはまだ
  • エラーを発見しないことが判明しました

    これらの3つの別々の戻り値のそれぞれを別々に扱いたい限り、約束は自然にエラーとエラーを分離しないので、自分の分岐のいくつかを追加しますgic。

    ブランチングを正常に実行するには、追加のレベルのネストが必要です。通常は、ロジックを理解して理解するのにコードを最も簡単にするため、それを避ける理由はありません。

    .post(function(req, res, next) { 
        findUsersExistingGame(...).then(function(game) { 
         if (game) return game; 
         return findUserWaitingForOpponentsGame(...).then(function(game) { 
          if (game) return game; 
          // createNewGame() either resolves with a valid game or rejects with an error 
          return createNewGame(...); 
         }); 
        }).then(function(game) { 
         res.send(game); 
        }, function(err) { 
         // send an error response here 
        }); 
    }); 
    

    これは、各段階での復帰を簡素化している、そしてそれは、物事のチェーンを作るために、次のネストされた約束を返し、それが全体的なコードを減らすために一箇所に応答を送信する処理を集中しているかに注意してください。


    さて、あなたはあなたの各機能は、前回のゲームの値を受け入れ、彼らがすでに有効なゲームがあるかどうかを確認しており、もしそうなら、彼らは何もしないことによって、このロジックの一部を隠すことができ

    .post(function(req, res, next) { 
        findUsersExistingGame(args) 
         .then(findUserWaitingForOpponentsGame) 
         .then(createNewGame) 
         .then(function(game) { 
          res.send(game); 
         }, function(err) { 
          // send an error response here 
         }); 
    }); 
    

    findUserWaitingForOpponentsGame()の中には、findUsersExistingGame()が解決した正確な引数を受け入れる必要があり、ゲームが有効かどうかを確認する必要があります。

    function findUserWaitingForOpponentsGame(args) { 
        if (args.game) { 
         return Promise.resolve(args); 
        } else { 
         return doAsyncFindUserWaitingForOpponentsGame(args); 
        } 
    } 
    

    各機能は、その上に任意の一般的なパラメータを持っていたし、各レベルがチェックできる.gameプロパティを持っていた引数のオブジェクトに解決します。これにより、きれいな制御フローが得られますが、各関数に余分なコードが作成され、各関数が前の関数の出力である引数を受け入れるようになります(直鎖を持つことができます)。あなたはあなたが好きなものを決めることができます。

  • +0

    は、 '.catch'を使う方が良いでしょうか?' findUsersExistingGame'と 'findUserWaitingForOpponentsGame'でエラーを捕まえることができますか? – PDN

    +0

    @PDN - これは、動作がそれらのエラーの対象となるものによって異なります。エラーをカスタム処理し、連鎖を続行したい場合は、 "yes"を指定するとローカル拒否ハンドラが必要になりますので、そこにコードを置くことができます。 '.post'全体がエラーで応答したい場合は、チェーン内のどこかでエラーが発生すると、それは今書かれています。エラーは「エラー応答をここに送信する」と書かれているトップレベルにまで伝搬します。私の実装では、成功とエラーの両方の応答処理を集中化しようとしました。 – jfriend00

    関連する問題