それでは、if-elseを約束で処理する方法は?


86

場合によっては、promiseオブジェクトから戻り値を取得するときにthen()、値の条件に応じて、次のように2つの異なるプロセスを開始する必要があります。

promise().then(function(value){
    if(//true) {
        // do something
    } else {
        // do something 
    }
})

多分私はそれを次のように書くことができると思っています:

promise().then(function(value){
    if(//true) {
        // call a new function which will return a new promise object
        ifTruePromise().then();
    } else {
        ifFalsePromise().then();
    }
})

しかし、これに関して、私は2つの質問があります:

  1. 新しいpromiseを開始してから、promiseでプロセスを開始するのが良い考えかどうかはわかりません。

  2. 最後に1つの関数を呼び出すために2つのプロセスが必要な場合はどうなりますか?それは彼らが同じ「ターミナル」を持っていることを意味します

私は元のチェーンを次のように保つために新しい約束を返そうとしました:

promise().then(function(value){
    if(//true) {
        // call a new function which will return a new promise object
        // and return it
        return ifTruePromise();
    } else {
        // do something, no new promise
        // hope to stop the then chain
    }
}).then(// I can handle the result of ifTruePromise here now);

しかし、この場合、それが真であろうと偽でthenあろうと、次は機能します。

それで、それを処理するためのベストプラクティスは何ですか?


1
これはあなたが探しているものかもしれませんstackoverflow.com/questions/26599798/…
vinayr 2015年

回答:


60

関数がpromiseを返す限り、提案した最初の方法を使用できます。

以下のフィドルは、最初に解決された値に応じて、さまざまなチェーンパスを使用する方法を示しています。

function myPromiseFunction() {
	//Change the resolved value to take a different path
    return Promise.resolve(true);
}

function conditionalChaining(value) {
    if (value) {
        //do something
        return doSomething().then(doSomethingMore).then(doEvenSomethingMore);
    } else {
        //do something else
        return doSomeOtherThing().then(doSomethingMore).then(doEvenSomethingMore);
    }
}

function doSomething() {
    console.log("Inside doSomething function");
    return Promise.resolve("This message comes from doSomeThing function");
}

function doSomeOtherThing() {
    console.log("Inside doSomeOtherthing function");
    return Promise.resolve("This message comes from doSomeOtherThing function");
}

function doSomethingMore(message) {
    console.log(message);
    return Promise.resolve("Leaving doSomethingMore");
}

function doEvenSomethingMore(message) {
    console.log("Inside doEvenSomethingMore function");
    return Promise.resolve();
}

myPromiseFunction().then(conditionalChaining).then(function () {
    console.log("All done!");
}).
catch (function (e) {

});

また、条件付きチェーンを1つ作成し、変数にreturn promiseを割り当ててから、どちらの方法でも実行する必要のある関数を実行し続けることもできます。

function conditionalChaining(value){
    if (value) {
        //do something
        return doSomething();
    } else{
        //do something else
        return doSomeOtherThing();
    }
}

var promise = myPromiseFunction().then(conditionalChaining);

promise.then(function(value){
    //keep executing functions that should be called either way
});

4

条件付きpromiseを使用するための簡単なパッケージを作成しました。

あなたがそれをチェックしたい場合:

npmページ:https//www.npmjs.com/package/promise-tree

およびgithub:https//github.com/shizongli94/promise-tree

パッケージが問題をどのように解決するかを尋ねるコメントに応えて:

1、2つのオブジェクトがあります。

2、このパッケージのブランチオブジェクトは、then()またはcatch()で使用するonFulfilledやonRejectedなどの関数の一時的な保存場所です。これには、Promiseの対応するものと同じ引数を取るthen()やcatch()などのメソッドがあります。Branch.then()またはBranch.catch()でコールバックを渡すときは、Promise.then()およびPromise.catch()と同じ構文を使用します。次に、コールバックを配列に格納する以外に何もしません。

3、Conditionは、チェックと分岐のための条件とその他の情報を格納するJSONオブジェクトです。

4、promiseコールバックで条件オブジェクトを使用して条件(ブール式)を指定します。次に、Conditionは、渡された情報を格納します。必要なすべての情報がユーザーによって提供された後、conditionオブジェクトはメソッドを使用して、Branchオブジェクトに以前に格納されたpromiseチェーンとコールバック情報を取得する完全に新しいPromiseオブジェクトを構築します。ここで少し注意が必要なのは、保存されたコールバックをチェーンする前に、(ユーザーではなく実装者として)最初に手動で作成したPromiseを解決/拒否する必要があることです。そうしないと、新しいプロミスチェーンが開始されないためです。

5、イベントループのおかげで、ブランチオブジェクトは、ステムPromiseオブジェクトを作成する前でも後でもインスタンス化でき、相互に干渉することはありません。構造が木に似ているので、ここでは「枝」と「茎」という用語を使用します。

サンプルコードは、npmページとgithubページの両方にあります。

ちなみに、この実装では、ブランチ内にブランチを作成することもできます。また、ブランチは、条件を確認するのと同じ場所にある必要はありません。


回答ではなくコメントを提供しているようです。十分な評判得られたら、どの投稿にもコメントできるようになります。また、代わりに何ができるかを確認してください。
thewaywewere 2017

@thewaywewere、私はあなたの要求に応えて実装の詳細を追加しました。
szl1919 2017

0

これは、fetch()で行った方法です。これが正しい方法かどうかはわかりませんが、機能します。

 fetch().then(res => res.ok ? res : false).then(res => {
    if (res) {
        //res ok
    } else {
       //res not ok
    }

});
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.