假设我有4个函数:runA()、runB()、runC()和runD()。
使用ES6 promises,在一个完全成功的运行中,所有这些都将一个接一个地运行:
runA()
.then(runB)
.then(runC)
.then(runD)如果runA或runB失败(拒绝或抛出),我想调用error1(),然后完全停止链(而不是调用runC或runD )。这让我觉得应该在.then promise链的末尾添加一个.catch():
runA()
.then(runB)
.then(runC) //won't get called if runA or runB throws
.then(runD) //won't get called if runA or runB throws
.catch(error1)但是如果runC失败了,我想调用error2()并且仍然停止链(而不是调用runD)。
runA()
.then(runB)
.catch(error1) //moved up to only handle runA and runB
.then(runC) //but now this gets called after error1() is run
.then(runD)
.catch(error2)现在链中有2个catch调用,runC将在error1运行后调用,因为捕获的结果将缺省为resolve。我唯一的选择是让error1函数创建一个它总是拒绝的promise吗?
发布于 2016-02-12 23:02:39
不,让error1创建一个总是拒绝的承诺,不是你唯一的选择。
您可以利用.then接受两个参数的事实:
.then(onSuccess, onFailure)当给出两个参数时,有一种被低估的效果,即onFailure将 onSuccess中的捕获失败。这通常是不可取的,除了这里,您可以使用此事实来分支您的决策树:
runA()
.then(runB)
.then(() => runC().then(runD), error1)
.catch(error2)这就是你想要的。
runA或runB失败,则调用error1并停止链。runC或runD失败,则调用<代码>D19并停止链。你也可以这样写它:
runA()
.then(runB)
.then(() => runC()
.then(runD)
.catch(error2),
error1)
var log = msg => div.innerHTML += "<br>" + msg;
// Change which one of these four rejects, to see behavior:
var runA = () => Promise.resolve().then(() => log("a"));
var runB = () => Promise.reject().then(() => log("b"));
var runC = () => Promise.resolve().then(() => log("c"));
var runD = () => Promise.resolve().then(() => log("d"));
var error1 = () => log("error1");
var error2 = () => log("error2");
runA()
.then(runB)
.then(() => runC().then(runD), error1)
.catch(error2)<div id="div"></div>
尝试在this fiddle中修改哪个失败。
发布于 2015-12-24 16:27:50
只使用一个.catch()有什么问题吗?您可以在catch回调(if (error1) error1() else if (error2) error2()...)中进行错误分类。抛出的Error对象可以有一条消息和一个名称(可以是您需要的类型,例如'RunCError‘)。
runA()
.then(runB)
.then(runC) // won't get called if runA or runB throws
.then(runD) // won't get called if runA or runB throws
.catch(handleErrors)
function runA() {
// ...
if (err) {
var error = new Error('Something is wrong...');
error.name = 'RunAError';
throw error;
}
}
function runB() {
// ...
if (err) {
var error = new Error('Something is wrong...');
error.name = 'RunBError';
throw error;
}
}
function runC() {
// ...
if (err) {
var error = new Error('Something is wrong...');
error.name = 'RunCError';
throw error;
}
}
function runD() {
// ...
if (err) {
var error = new Error('Something is wrong...');
error.name = 'RunDError';
throw error;
}
}
function handleErrors(err) {
if (err.name == 'RunAError') {
handleAError();
}
if (err.name == 'RunBError') {
handleBError();
}
// so on...
}发布于 2016-12-08 16:41:55
我碰巧遇到了同样的问题,到目前为止,我的解决方案是显式地调用catch中的reject,比如js:https://jsbin.com/yaqicikaza/edit?js,console
代码片段
const promise1 = new Promise( ( resolve, reject ) => reject( 42 ) );
promise1
.catch( ( err ) => console.log( err ) ) // 42 will be thrown here
.then( ( res ) => console.log( 'will execute' ) ) // then branch will execute
const promise2 = new Promise( ( resolve, reject ) => reject( 42 ) );
promise2
.catch( ( err ) => Promise.reject( ) ) // trigger rejection down the line
.then( ( res ) => console.log( 'will not execute' ) ) // this will be skipped
https://stackoverflow.com/questions/34448493
复制相似问题