Jak więc poradzić sobie z obietnicą if-else?

86

W niektórych przypadkach, gdy otrzymam wartość zwracaną z obiektu obietnicy, muszę rozpocząć dwie różne then()procedury zależne od stanu wartości, na przykład:

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

Myślę, że może mógłbym to napisać tak:

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

ale w związku z tym mam dwa pytania:

  1. Nie jestem pewien, czy to dobry pomysł, aby rozpocząć nową obietnicę, a następnie przetworzyć obietnicę;

  2. co, jeśli potrzebuję dwóch procesów, aby wywołać jedną funkcję w ostatniej? Oznacza to, że mają ten sam „terminal”

Próbowałem zwrócić nową obietnicę zachowania oryginalnego łańcucha, jak:

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);

ale w tym przypadku, czy to prawda, czy fałsz, następny thenzadziała.

Więc jaka jest najlepsza praktyka, aby sobie z tym poradzić?

Brick Yang
źródło
1
może to jest to, czego szukasz stackoverflow.com/questions/26599798/… ?
vinayr

Odpowiedzi:

60

Tak długo, jak Twoje funkcje zwracają obietnicę, możesz użyć pierwszej sugerowanej metody.

Poniższe skrzypce pokazują, jak możesz wybrać różne ścieżki łańcuchowe w zależności od tego, jaka będzie pierwsza rozstrzygnięta wartość.

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) {

});

Możesz także po prostu utworzyć jeden łańcuch warunkowy, przypisać obietnicę zwrotu do zmiennej, a następnie kontynuować wykonywanie funkcji, które powinny być uruchamiane w obie strony.

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
});
Daniel B.
źródło
4

Napisałem prosty pakiet do warunkowego stosowania przyrzeczenia.

Jeśli chcesz to sprawdzić:

Strona npm: https://www.npmjs.com/package/promise-tree

i github: https://github.com/shizongli94/promise-tree

W odpowiedzi na uwagi z pytaniem, jak pakiet rozwiązuje problem:

1, ma dwa obiekty.

2, obiekt Branch w tym pakiecie jest tymczasowym miejscem przechowywania funkcji, takich jak onFulfilled i onRejected, których chcesz użyć w then () lub catch (). Posiada metody, takie jak then () i catch (), które pobierają te same argumenty, co ich odpowiedniki w Promise. Kiedy przekazujesz wywołanie zwrotne w Branch.then () lub Branch.catch (), użyj tej samej składni, co Promise.then () i Promise.catch (). Następnie nie rób nic poza przechowywaniem wywołań zwrotnych w tablicy.

3, Stan to obiekt JSON, który przechowuje warunki i inne informacje do sprawdzania i rozgałęziania.

4. Określasz warunki (wyrażenie boolowskie) za pomocą obiektu warunku w wywołaniach zwrotnych obietnicy. Warunek następnie przechowuje informacje, które przekazujesz. Po dostarczeniu wszystkich niezbędnych informacji przez użytkownika, obiekt warunku używa metody do skonstruowania zupełnie nowego obiektu Promise, który przyjmuje informacje z łańcucha obietnic i wywołań zwrotnych, które zostały wcześniej zapisane w obiekcie Branch. Trochę trudna część polega na tym, że Ty (jako osoba wdrażająca, a nie użytkownik) musisz rozwiązać / odrzucić obietnicę, którą najpierw zbudowałeś ręcznie, zanim połączysz zapisane wywołania zwrotne. Dzieje się tak, ponieważ w przeciwnym razie nowy łańcuch obietnic nie rozpocznie się.

5, Dzięki pętli zdarzeń obiekty Branch mogą być tworzone przed lub po utworzeniu macierzystego obiektu Promise i nie będą ze sobą kolidować. Używam tutaj terminów „gałąź” i „łodyga”, ponieważ struktura przypomina drzewo.

Przykładowy kod można znaleźć na stronach npm i github.

Nawiasem mówiąc, ta implementacja umożliwia również posiadanie oddziałów w oddziale. A oddziały nie muszą znajdować się w tym samym miejscu, w którym sprawdzasz warunki.

szl1919
źródło
Wygląda na to, że zamiast odpowiedzi podajesz komentarze. Gdy zdobędziesz wystarczającą reputację , będziesz mógł komentować każdy post. Sprawdź też, co mogę zamiast tego zrobić .
thewaywewewere
@thewaywewere, dodałem szczegóły implementacji w odpowiedzi na Twoją prośbę.
szl1919
0

Tak to zrobiłem w moim fetch () Nie jestem pewien, czy to jest właściwy sposób, ale działa

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

});
Servus
źródło