Então, como lidar com o if-else na promessa?


86

Em alguns casos, quando obtenho um valor de retorno de um objeto de promessa, preciso iniciar dois then()precessos diferentes, dependendo da condição do valor, como:

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

Estou pensando que talvez possa escrever assim:

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

mas com isso, tenho duas perguntas:

  1. Não tenho certeza se é uma boa ideia começar uma nova promessa e depois processar em uma promessa;

  2. e se eu precisar que os dois processos chamem uma função no último? Isso significa que eles têm o mesmo "terminal"

Tentei devolver a nova promessa de manter a corrente original como:

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

mas, neste caso, seja verdadeiro ou falso, o próximo thenfuncionará.

Então, qual é a melhor prática para lidar com isso?


1
pode ser isso que você está procurando stackoverflow.com/questions/26599798/… ?
vinayr

Respostas:


60

Contanto que suas funções retornem uma promessa, você pode usar o primeiro método que sugerir.

O violino abaixo mostra como você pode seguir diferentes caminhos de encadeamento, dependendo de qual será o primeiro valor resolvido.

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

});

Você também pode fazer apenas um encadeamento condicional, atribuir a promessa de retorno a uma variável e, em seguida, continuar executando as funções que devem ser executadas de qualquer maneira.

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

Eu escrevi um pacote simples para uso de promessa condicional.

Se você quiser dar uma olhada:

página npm: https://www.npmjs.com/package/promise-tree

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

Em resposta a comentários perguntando como o pacote resolve o problema:

1, tem dois objetos.

2, o objeto Branch neste pacote é um local de armazenamento temporário para as funções como onFulfilled e onRejected que você deseja usar em then () ou catch (). Ele tem métodos como then () e catch () que usam os mesmos argumentos das contrapartes em Promise. Ao passar um retorno de chamada em Branch.then () ou Branch.catch (), use a mesma sintaxe de Promise.then () e Promise.catch (). Em seguida, não faça nada além de armazenar os retornos de chamada em uma matriz.

3, Condition é um objeto JSON que armazena as condições e outras informações para verificação e ramificação.

4, você especifica as condições (expressão booleana) usando o objeto de condição em retornos de chamada de promessa. Condition, então, armazena as informações que você passa. Depois que todas as informações necessárias são fornecidas pelo usuário, o objeto de condição usa um método para construir um objeto Promise completamente novo que recebe informações de cadeia de promessa e retorno de chamada previamente armazenadas no objeto Branch. Uma pequena parte complicada aqui é que você (como o implementador, não o usuário) precisa resolver / rejeitar a Promessa que você construiu manualmente antes de encadear os retornos de chamada armazenados. Isso ocorre porque, caso contrário, a nova cadeia de promessa não será iniciada.

5, Graças ao loop de evento, os objetos Branch podem ser instanciados antes ou depois de você ter um objeto Promise de radical e eles não interferirão uns com os outros. Eu uso os termos "galho" e "caule" aqui porque a estrutura se assemelha a uma árvore.

O código de exemplo pode ser encontrado nas páginas npm e github.

A propósito, esta implementação também permite que você tenha ramificações dentro de uma ramificação. E as filiais não precisam estar no mesmo lugar em que você verifica as condições.


Parece que você está fornecendo comentários em vez de resposta. Assim que tiver reputação suficiente, você poderá comentar em qualquer postagem. Verifique também o que posso fazer em vez disso .
thewaywere

@thewaywewere, adicionei detalhes de implementação em resposta à sua solicitação.
szl1919

0

Foi assim que fiz no meu fetch () Não tenho certeza se esse é o caminho certo, mas funciona

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

});
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.