我怎样才能像传统的 'return' 语句一样绕过承诺链中的其余“then”?
How can I bypass the rest of the 'then's in a promise chain, like a traditional 'return' statement?
我将离开我的同步、多线程 Java 编程世界,拥抱单线程、异步、基于 promise 的 ES6 JavaScript 世界。我不得不理解将以同步方式编写的函数映射到基于 promise 的异步函数的概念。我目前正在混合使用 ES6 原生 Promises 和 bluebird promises。
我将从一个示例开始为我的问题做准备(同步示例在 Java 中,异步示例在 ES6 中):
同步函数
private Object doSomething(Object var1, Object var2) {
Object var3 = blockingFunction(var1);
Object var4 = anotherBlockingFunction(var2, var3);
return var4;
}
基于异步 Promise 的 equivlanet
function doSomething(var1, var2) {
return asyncFunction(var1)
.then(var3 => {
return anotherAsyncFunction(var2, var3);
})
.then(var4 => {
return var4;
});
}
现在这是我的问题:是否有一种干净的(即内置的,已经想到的)方法来模拟同步 return
绕过其余部分的想法return 链条?
为了说明,这里再举两个同步和异步的例子:
同步函数
private Object doSomething(Object var1, Object var2) {
Object var3 = blockingFunction(var1);
Object var4 = anotherBlockingFunction(var2, var3);
if (!var4.isValid()) {
return var3;
}
// If var4.isValid() equates to false, we bypass the following statements
// and return the value of var3 as the final value
Object var5 = var4.validateObject();
var5.setSomething(var1);
return var5;
}
(我的猜测)基于异步 Promise 的等价物
function doSomething(var1, var2) {
// Predefine variables within this block so they persist between 'then's
let var3;
let var4;
let var5;
let bypassCondition;
return asyncFunction(var1)
.then(result => {
var3 = result;
return anotherAsyncFunction(var2, var3);
})
.then(result => {
var4 = result;
bypassCondition = !var4.valid;
if(bypassCondition) {
return var3;
}
})
.endChain(bypassCondition)
// If the bypassCondition is true, the entire chain would return the value
// of the previous then's return;
// Otherwise, if false, the chain continues
.then(() => {
return var4.validateObject();
})
.then(result => {
var5 = result;
var5.something = var1;
return var5;
});
}
这样的东西已经存在了吗?
我知道这些备选方案,所以也许我可以判断其中任何一个是否真的是正确的方法:
- 在链的中间抛出异常,在末端捕获,从而绕过其他语句
- 将每个后续
then
的函数包装在一个 if (!bypassCondition)
块中,这样它们就不会全部被执行
你在谈论承诺链中的条件流,其中早期 return 是一种有用的风格。
是的,这是可能的,通过有条件地分支你的链。注意括号:
function doSomething(var1, var2) {
return asyncFunction(var1)
.then(var3 => anotherAsyncFunction(var2, var3))
.then(var4 => (!var4.isValid())? var3 : var4.validateObject()
.then(var5 => (var5.something = var1, var5)));
}
注意最后一行的缩进,其中 .then
与 var4.validateObject()
不同。
这很好地映射到 ES7(我们可以提前保释启动):
async function doSomething(var1, var2) {
let var3 = await asyncFunction(var1);
let var4 = await anotherAsyncFunction(var2, var3);
if (!var4.isValid()) {
return var3;
}
let var5 = await var4.validateObject();
var5.something = var1;
return var5;
}
(你没有指定 validateObject
是否是异步的,所以我选择了异步)。
是我能够得到这个问题的答案的地方。
正如 Bergi 所指出的,我在这里所做的是分支。我需要做的就是将继续分支 放在 else 块中,如下所示:
function doSomething(var1, var2) {
// Predefine variables within this block so they persist between 'then's
let var3;
let var4;
let var5;
return asyncFunction(var1)
.then(result => {
var3 = result;
return anotherAsyncFunction(var2, var3);
})
.then(result => {
var4 = result;
if(!var4.valid) {
return var3;
}
else {
return Promise.resolve()
.then(() => {
return var4.validateObject();
})
.then(result => {
var5 = result;
var5.something = var1;
return var5;
});
})
}
}
从根本上说,您不能停止承诺链。尽管看起来我应该可以,但请记住其他函数会将 .then(...)
附加到您的函数的输出。代码没有区分 then
语句出现在一个函数内还是函数外,所以我提议的 .endchain(...)
必须结束承诺链的所有其他用户 在函数之外,使链最终无法使用。
使用这种分支方法,我所追求的传统 return
行为就完成了,因为函数结束前链中的最后一个 then
是链将在其执行时拾取的地方return 值在函数外部使用——在这种情况下,如果 var4.valid
是 false
,则在 return var3;
之后,否则在 return var5;
之后。
我将离开我的同步、多线程 Java 编程世界,拥抱单线程、异步、基于 promise 的 ES6 JavaScript 世界。我不得不理解将以同步方式编写的函数映射到基于 promise 的异步函数的概念。我目前正在混合使用 ES6 原生 Promises 和 bluebird promises。
我将从一个示例开始为我的问题做准备(同步示例在 Java 中,异步示例在 ES6 中):
同步函数
private Object doSomething(Object var1, Object var2) {
Object var3 = blockingFunction(var1);
Object var4 = anotherBlockingFunction(var2, var3);
return var4;
}
基于异步 Promise 的 equivlanet
function doSomething(var1, var2) {
return asyncFunction(var1)
.then(var3 => {
return anotherAsyncFunction(var2, var3);
})
.then(var4 => {
return var4;
});
}
现在这是我的问题:是否有一种干净的(即内置的,已经想到的)方法来模拟同步 return
绕过其余部分的想法return 链条?
为了说明,这里再举两个同步和异步的例子:
同步函数
private Object doSomething(Object var1, Object var2) {
Object var3 = blockingFunction(var1);
Object var4 = anotherBlockingFunction(var2, var3);
if (!var4.isValid()) {
return var3;
}
// If var4.isValid() equates to false, we bypass the following statements
// and return the value of var3 as the final value
Object var5 = var4.validateObject();
var5.setSomething(var1);
return var5;
}
(我的猜测)基于异步 Promise 的等价物
function doSomething(var1, var2) {
// Predefine variables within this block so they persist between 'then's
let var3;
let var4;
let var5;
let bypassCondition;
return asyncFunction(var1)
.then(result => {
var3 = result;
return anotherAsyncFunction(var2, var3);
})
.then(result => {
var4 = result;
bypassCondition = !var4.valid;
if(bypassCondition) {
return var3;
}
})
.endChain(bypassCondition)
// If the bypassCondition is true, the entire chain would return the value
// of the previous then's return;
// Otherwise, if false, the chain continues
.then(() => {
return var4.validateObject();
})
.then(result => {
var5 = result;
var5.something = var1;
return var5;
});
}
这样的东西已经存在了吗?
我知道这些备选方案,所以也许我可以判断其中任何一个是否真的是正确的方法:
- 在链的中间抛出异常,在末端捕获,从而绕过其他语句
- 将每个后续
then
的函数包装在一个if (!bypassCondition)
块中,这样它们就不会全部被执行
你在谈论承诺链中的条件流,其中早期 return 是一种有用的风格。
是的,这是可能的,通过有条件地分支你的链。注意括号:
function doSomething(var1, var2) {
return asyncFunction(var1)
.then(var3 => anotherAsyncFunction(var2, var3))
.then(var4 => (!var4.isValid())? var3 : var4.validateObject()
.then(var5 => (var5.something = var1, var5)));
}
注意最后一行的缩进,其中 .then
与 var4.validateObject()
不同。
这很好地映射到 ES7(我们可以提前保释启动):
async function doSomething(var1, var2) {
let var3 = await asyncFunction(var1);
let var4 = await anotherAsyncFunction(var2, var3);
if (!var4.isValid()) {
return var3;
}
let var5 = await var4.validateObject();
var5.something = var1;
return var5;
}
(你没有指定 validateObject
是否是异步的,所以我选择了异步)。
正如 Bergi 所指出的,我在这里所做的是分支。我需要做的就是将继续分支 放在 else 块中,如下所示:
function doSomething(var1, var2) {
// Predefine variables within this block so they persist between 'then's
let var3;
let var4;
let var5;
return asyncFunction(var1)
.then(result => {
var3 = result;
return anotherAsyncFunction(var2, var3);
})
.then(result => {
var4 = result;
if(!var4.valid) {
return var3;
}
else {
return Promise.resolve()
.then(() => {
return var4.validateObject();
})
.then(result => {
var5 = result;
var5.something = var1;
return var5;
});
})
}
}
从根本上说,您不能停止承诺链。尽管看起来我应该可以,但请记住其他函数会将 .then(...)
附加到您的函数的输出。代码没有区分 then
语句出现在一个函数内还是函数外,所以我提议的 .endchain(...)
必须结束承诺链的所有其他用户 在函数之外,使链最终无法使用。
使用这种分支方法,我所追求的传统 return
行为就完成了,因为函数结束前链中的最后一个 then
是链将在其执行时拾取的地方return 值在函数外部使用——在这种情况下,如果 var4.valid
是 false
,则在 return var3;
之后,否则在 return var5;
之后。