Як тоді впоратися з обіцяним if-else?


86

У деяких випадках, коли я отримую повертане значення від об'єкта-обіцянки, мені потрібно запустити дві різні then()прецесії, які залежать від стану значення, наприклад:

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

але з цим у мене є два запитання:

  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

Відповіді:


60

Поки ваші функції повертають обіцянку, ви можете використовувати перший із запропонованих вами методів.

Скрипка нижче показує, як можна пройти різні ланцюгові шляхи залежно від того, яким буде перше вирішене значення.

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

});

Ви також можете просто зробити один умовний ланцюжок, призначити змінну обіцянку повернення, а потім продовжувати виконувати функції, які слід запускати в будь-якому випадку.

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

Я написав простий пакет для використання умовних обіцянок.

Якщо ви хочете перевірити це:

Сторінка npm: https://www.npmjs.com/package/promise-tree

та github: https://github.com/shizongli94/promise-tree

У відповідь на коментарі з проханням про те, як пакет вирішує проблему:

1, він має два об'єкти.

2, Об’єкт розгалуження в цьому пакеті є тимчасовим місцем зберігання таких функцій, як onFulfilled та onRejected, які ви хочете використовувати в then () або catch (). У ньому є такі методи, як then () і catch (), які беруть ті самі аргументи, що і аналоги в Promise. Коли ви передаєте зворотний виклик у Branch.then () або Branch.catch (), використовуйте той самий синтаксис, що Promise.then () та Promise.catch (). Тоді не робіть нічого, крім зберігання зворотних викликів у масиві.

3, Condition - це об’єкт JSON, який зберігає умови та іншу інформацію для перевірки та розгалуження.

4, Ви вказуєте умови (логічний вираз), використовуючи об'єкт умова в обіцяних зворотних викликах. Потім умова зберігає інформацію, яку ви передаєте. Після того, як вся необхідна інформація надана користувачем, об’єкт умова використовує метод для побудови абсолютно нового об’єкта Promise, який приймає інформацію про ланцюжок обіцянок та зворотний виклик, раніше збережену в об’єкті Branch. Трохи хитра частина тут полягає в тому, що вам (як реалізатору, а не користувачеві) доводиться вирішувати / відхиляти обіцянку, яку ви спочатку створили вручну, перед ланцюжком збережених зворотних викликів. Це тому, що в іншому випадку новий ланцюжок обіцянок не розпочнеться.

5, Завдяки циклу подій, об'єкти Branch можуть бути створені до або після того, як у вас є основний об'єкт Promise, і вони не будуть заважати один одному. Тут я використовую терміни "гілка" та "стебло", оскільки структура нагадує дерево.

Приклад коду можна знайти на сторінках npm та github.

До речі, ця реалізація також дає змогу мати філії всередині філії. І відділення не повинні знаходитися там же, де ви перевіряєте умови.


Схоже, ви надаєте коментарі замість відповіді. Отримавши достатню репутацію, ви зможете коментувати будь-яку публікацію. Також перевірте, що я можу зробити замість цього .
thewaywewere

@thewaywewere, я додав деталі реалізації, відповідаючи на ваш запит.
szl1919,

0

Ось як я це зробив у своєму fetch (). Я не впевнений, що це правильно, але це працює

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

});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.