2016-08-02 9 views
1

「ゴーストプロミス」という言葉が私の場合のように見えるhereが見つかりました。でも_check trueを返しますが、それはまだ(undefinedその結果)console.logコマンドに進み、約束パターンを修正する方法 - Ghost Promise?

return Q.Promise(function(resolve, reject) { 
    firstFunctionThatReturnPromise() 
    .then(function(firstResult) { 
    _check(firstResult) ? resolve(firstResult) : return secondFunctionThatReturnPromise(); 
    }) 
    .then(function(secondResult) { 
    console.log(secondResult); 
    return thirdFunctionThatReturnPromise(secondResult); 
    }) 
    .then(function(thirdResult) { 
    resolve(thirdResult); 
    }) 
    .catch(function(e) { 
    reject(e) 
    }); 
}); 

問題がある:

私はこのようなコードを持っています。

_checkがfalseを返す場合、期待どおりに動作します。

だから私の質問は次のとおりです。

  • 上記の動作が正常であれば?
  • このケースを処理するより洗練された方法がある場合は、

アップデート1:多くは、私が代わりに直接結果を返すのでQ.Promiseを使用する理由という疑問を呈しました。これは汎用関数であり、他の関数で共有されているからです。

// Usage in other functions 
genericFunction() 
.then(function(finalResult) { 
    doSomething(finalResult); 
}) 
.catch(function(err) { 
    handleError(err); 
}); 
+0

あなたは:これはgenericFunction内にある場合でも、あなたはまだあなたが既に持っている約束を返すことができ

firstFunctionThatReturnPromise().then(function (firstResult) { if (_check(firstResult)) { return firstResult; } else { return secondFunctionThatReturnPromise().then(function (secondResult) { console.log(secondResult); return thirdFunctionThatReturnPromise(secondResult); }) } }).then(function (finalResult) { console.log(finalResult); return finalResult; }).catch(function (err) { console.log(err); throw err; }); 

:あなたの擬似コードを使用して

が、それはこのようになりますここでは幽霊を持っていないが、平凡な['プロミス]コンストラクタ反パターン](http://stackoverflow.com/q/23803743/1048572)! – Bergi

答えて

2

まず、これについて新しい約束をする必要はありません。あなたの操作はすでに約束を返すので、新しい約束でそれらを再包装するのはerror prone anti-patternです。他の人が言っているよう

セカンドオフは、.then()ハンドラは、これらの選択肢があります。

  1. それは次の.then()ハンドラに渡される結果を返すことができます。何も返さないと、undefinedが次の.then()ハンドラに渡されます。
  2. 解決済みの値が次の.then()ハンドラに渡される約束を返すことができます。または拒否された値は、次の拒否ハンドラに渡されます。
  3. 現在の約束を拒否することができます。

は条件付きで拒否以外のいくつかの次.then()ハンドラをスキップする約束チェーンを伝えるために.then()ハンドラからの方法はありません。だから、

a().then(function(result1) { 
    if (result1) { 
     return result1; 
    } else { 
     // b() is only executed here in this conditional 
     return b().then(...); 
    } 
}).then(function(result2) { 
    // as long as no rejection, this is executed for both branches of the above conditional 
    // result2 will either be result1 or the resolved value of b() 
    // depending upon your conditional 
}) 

、あなたが分岐したい:あなたは、いくつかの条件ロジックに基づいてあなたの約束を分岐する場合

だから、あなたはあなたの分岐ロジックによると、実際に巣あなた.then()ハンドラをする必要があり条件付き分岐に基づいて何が起こるかを制御するための新しいネストされたチェーンを作成します。

function genericFunction() { 
    return firstFunctionThatReturnPromise().then(function (firstResult) { 
     if (_check(firstResult)) { 
      return firstResult; 
     } else { 
      return secondFunctionThatReturnPromise().then(function (secondResult) { 
       console.log(secondResult); 
       return thirdFunctionThatReturnPromise(secondResult); 
      }) 
     } 
    }).then(function (finalResult) { 
     console.log(finalResult); 
     return finalResult; 
    }).catch(function (err) { 
     console.log(err); 
     throw err; 
    }); 
} 

// usage 
genericFunction().then(...).catch(...) 
+0

あなたの答えをありがとう、私は私が約束ラッパーを使用する理由を追加する質問を編集します。 – haipham23

+1

@ haipham23 - これを約束の形で包む理由はまだありません。あなたはそれを返すために新しい約束をする必要はないということを理解していないようです。私の答えが示すように、すでに持っているものを返すことができます。 – jfriend00

+0

ありがとう、私は上記の指示に従って、それは完全に動作します! – haipham23

0

私はQを使用したことがないが、約束が返すすべてが約束に変換し、次の.then()に渡されます。ここでは、最初の.then()は何も返しません。したがって、undefinedを返します。したがって、undefinedは新しいPromiseにラップされ、次のハンドラに渡されます。ここでsecondResult == undefinedが得られます。

次CodePenでアクションでそれを見ることができます:http://codepen.io/JesmoDrazik/pen/xOaXKE

1

動作が期待されています。 .then()ステートメントをチェーン化すると、エラーを投げる以外は早期にチェーンから脱出することはできません。

の後にあなたのトップレベルの約束(Q.Promise()によって返されたもの)が解決されます。しかし、あなたは実際に実行し続ける内側の約束を持っています。 https://promisesaplus.com/#point-40

あなたはQのソースコードに自分で見ることができます:約束返しthen()仕様で

、ご希望の動作のためにhttps://github.com/kriskowal/q/blob/v1/q.js#L899

を、あなたは実際には別のネストされた約束のチェーンが必要になります。

return Q.Promise(function(resolve, reject) { 
    firstFunctionThatReturnPromise().then(function(firstResult) { 
    if (_check(firstResult)) { 
     resolve(firstResult); 
    } else { 
     return secondFunctionThatReturnPromise().then(function(secondResult) { 
     console.log(secondResult); 
     return thirdFunctionThatReturnPromise(secondResult); 
     }); 
    } 
    }); 
}); 
+2

すべての関数がすでに約束を返すと仮定すると、それらを 'Q.Promise'でラップする必要はありません。 'firstFunctionThatReturnPromise'によって返された約束を返してください(自動的にラップされるので、' firstResult'を明示的に返してください)。 – robertklep

関連する問題