¿Cómo manejar entonces la promesa si-si no?


86

En algún caso, cuando obtengo un valor de retorno de un objeto de promesa, necesito comenzar dos then()procesos diferentes dependiendo de la condición del valor, como:

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

Estoy pensando que tal vez pueda escribirlo así:

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

pero con esto, tengo dos preguntas:

  1. No estoy seguro de si es una buena idea comenzar una nueva promesa y luego procesarla;

  2. ¿Qué pasa si necesito los dos procesos para llamar a una función en el último? Significa que tienen el mismo "terminal"

Traté de devolver la nueva promesa para mantener la cadena 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);

pero en este caso, ya sea verdadero o falso, el siguiente thenfuncionará.

Entonces, ¿cuál es la mejor práctica para manejarlo?


1
puede ser que esto es lo que está buscando stackoverflow.com/questions/26599798/… ?
vinayr

Respuestas:


60

Siempre que sus funciones devuelvan una promesa, puede utilizar el primer método que sugiera.

El violín a continuación muestra cómo puede tomar diferentes rutas de encadenamiento dependiendo de cuál será el primer valor resuelto.

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

});

También puede simplemente hacer un encadenamiento condicional, asignar la promesa de retorno a una variable y luego seguir ejecutando las funciones que deben ejecutarse de cualquier manera.

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

He escrito un paquete simple para el uso de promesas condicionales.

Si quieres comprobarlo:

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

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

En respuesta a los comentarios que preguntan cómo el paquete resuelve el problema:

1, tiene dos objetos.

2, el objeto Branch en este paquete es un lugar de almacenamiento temporal para las funciones como onFul fill y onRejected que desea usar en then () o catch (). Tiene métodos como then () y catch () que toman los mismos argumentos que las contrapartes de Promise. Cuando pase una devolución de llamada en Branch.then () o Branch.catch (), use la misma sintaxis que Promise.then () y Promise.catch (). Luego no haga nada más que almacenar las devoluciones de llamada en una matriz.

3, Condition es un objeto JSON que almacena las condiciones y otra información para verificar y ramificar.

4, usted especifica condiciones (expresión booleana) usando el objeto de condición en las devoluciones de llamada de promesa. La condición entonces almacena la información que usted pasa. Una vez que el usuario proporciona toda la información necesaria, el objeto condición utiliza un método para construir un objeto Promise completamente nuevo que toma la información de la cadena de promesa y la devolución de llamada almacenada previamente en el objeto Branch. Una pequeña parte complicada aquí es que usted (como implementador, no usuario) tiene que resolver / rechazar la Promesa que construyó primero manualmente antes de encadenar las devoluciones de llamada almacenadas. Esto se debe a que, de lo contrario, la nueva cadena de promesas no comenzará.

5, gracias al bucle de eventos, los objetos Branch se pueden instanciar antes o después de tener un objeto Promise de raíz y no interferirán entre sí. Utilizo los términos "rama" y "tallo" aquí porque la estructura se asemeja a un árbol.

El código de ejemplo se puede encontrar en las páginas de npm y github.

Por cierto, esta implementación también le permite tener sucursales dentro de una sucursal. Y las sucursales no tienen que estar en el mismo lugar donde verifica las condiciones.


Parece que está proporcionando comentarios en lugar de respuestas. Una vez que tengas suficiente reputación , podrás comentar cualquier publicación. También verifique esto, ¿qué puedo hacer en su lugar ?
thewaywewere

@thewaywewere, he agregado detalles de implementación en respuesta a su solicitud.
szl1919

0

Así es como lo hice en mi fetch () No estoy seguro si esta es la manera correcta, pero funciona

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

});
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.