如何处理如果-否则在承诺?

在某些情况下,当我从一个承诺对象获得一个返回值时,我需要根据该值的条件启动两个不同的 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将工作。

那么,处理这个问题的最佳实践是什么?

104380 次浏览

As long as your functions return a promise, you can use the first method that you suggest.

The fiddle below shows how you can take different chaining paths depending on what the first resolved value will be.

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


});

You can also just make one conditional chaining, assign the return promise to a variable and then keep executing the functions that should be run either way.

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

I have written a simple package for conditional promise usage.

If you want to check it out:

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

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

In response of comments asking for how the package solves the problem:

1, It has two objects.

2, Branch object in this package is a temporary storage place for the functions such as onFulfilled and onRejected that you want to use in then() or catch(). It has methods such as then() and catch() which take the same arguments as the counterparts in Promise. When you pass in a callback in Branch.then() or Branch.catch(), use the same syntax as Promise.then() and Promise.catch(). Then do nothing but storing the callbacks in an array.

3, Condition is a JSON object that stores the conditions and other information for checking and branching.

4, You specify conditions (boolean expression) using condition object in promise callbacks. Condition then stores the information you pass in. After all necessary information is provided by user, condition object uses a method to construct completely new Promise object that takes promise chain and callback information previously stored in Branch object. A little tricky part here is that you (as the implementer, not user) have to resolve/reject the Promise you first constructed manually before chaining the stored callbacks. This is because otherwise, the new promise chain won't start.

5, Thanks to event loop, Branch objects can be instantiated either before or after you have a stem Promise object and they won't interfere with each other. I use the terms "branch" and "stem" here because the structure resembles a tree.

Example code can be found on both npm and github pages.

By the way, this implementation also enables you have branches within a branch. And branches do not have to be at the same place you check conditions.

This is how I did it in my fetch() I am not sure if this is the right way, but it works

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


});