Javascript 如何区分错误';基于承诺链中阶段的s源

Javascript 如何区分错误';基于承诺链中阶段的s源,javascript,es6-promise,Javascript,Es6 Promise,我有两个回调函数,都调用API并返回Promise。它们应该按顺序进行。让我们把它们命名为verifyThing和updateThing 因此,如果没有错误处理,它将与 verifyThing() .then((id) => updateThing(id)) 但现在,错误处理出现了。假设我需要在验证失败或更新失败后显示不同的错误消息。同样很明显,如果验证失败,我不需要调用updateThing 到目前为止,我已尝试使用自定义错误: class VerifyError extends E

我有两个回调函数,都调用API并返回
Promise
。它们应该按顺序进行。让我们把它们命名为
verifyThing
updateThing

因此,如果没有错误处理,它将与

verifyThing()
 .then((id) => updateThing(id))
但现在,错误处理出现了。假设我需要在验证失败或更新失败后显示不同的错误消息。同样很明显,如果
验证失败,我不需要调用
updateThing

到目前为止,我已尝试使用自定义错误:

class VerifyError extends Error {};
verifyThing()
  .catch(e => {
    message("cannot verify");
    throw new VerifyError();
  })
 .then((id) => updateThing(id))
 .catch(e => {
   if (e instanceof VerifyError) return;
   message("cannot update");
 })

不幸的是,我们使用的Babel6.26出现了自定义错误。作为一个脏补丁,我可以抛出magicstring而不是Error子类,但是ESLint规则是有原因的,对吗

最后我得到了工作变量。但我认为它的可读性较差(因为嵌套):


是否有其他方法来处理同一链中的所有逻辑?

似乎可以通过对上一个示例重新排序来实现您想要的实际行为:

verifyThing().then(id => 
  updateThing(id).catch(e => {
    message("cannot update");
  })
).catch(e => {
  message("cannot verify");
})
外部的
catch()
将只捕获来自
verifyThing()
的错误,因为内部的
catch()
已经处理了来自
updateThing(id)
的错误。此外,您总是得到已解决的承诺,而不是拒绝的承诺,这是适当的,因为这两种类型的错误都已经处理过了

为避免出现错误处理不靠近源的情况,请将内部部分移动到辅助函数:

function tryUpdateThing (id) {
  return updateThing(id).catch(e => {
    message("cannot update");
  });
}

verifyThing().then(
  tryUpdateThing
).catch(e => {
  message("cannot verify");
});

这是否可读,我将由您决定。

如果
async/await
是一个选项,那么:

async function() {
    let id;
    try {
        id = await verifyThing();
        await updateThing(id);
    } catch(e) {
        message(id === undefined ? "cannot verify" : "cannot update");
        throw e;
    }
}

这假设当
verifyThing()
满足时,它将使用定义的值进行解析。

为什么不直接抛出相应子类型(或错误本身)的本机错误,而不是扩展?在上一个示例中,
id
可以是
未定义的
。那真的是你想要的吗?如果验证失败,我不需要调用
updateThing
。换句话说,您的上一个示例确实调用了
updateThing
,即使
verifyThing
失败。哦,是的,您是对的。尝试提供一些我丢失的
throw
的最小示例。已修复。您认为适当子类型的错误是什么意思?
?一个典型的做法是将id存储在子类错误上。不是按实例检查,而是按id检查。顺便说一句,这可以避免对您有多少错误进行n次子类化。谢谢您的示例。我的错误,我的上一个代码示例错过了
throw
,因此无法按要求工作。实际上,如果可能的话,我希望避免嵌套
.then()
/
.catch()
,并使错误处理尽可能靠近错误源。你觉得怎么样?@skyboyer错误处理尽可能接近源代码。当你将
updateThing(id).catch(e=>{message(“cannot update”);})
移动到一个helper函数时,这一点更为明显。@skyboyer嵌套的
catch
看起来很不幸,但我认为这是处理这类事情的最好方法(
message
最好不要抛出,对吗?),还感谢您将call+
catch
封装到命名的
try…
函数中。看起来(几乎)理想。完全有道理。为了扩展更多步骤,我可能会引入额外的变量
errorMessageToShowIfFailOnNextStep
,因此在
catch()
中,即使没有
if/else
,我也会有相关的错误消息。谢谢
async function() {
    let id;
    try {
        id = await verifyThing();
        await updateThing(id);
    } catch(e) {
        message(id === undefined ? "cannot verify" : "cannot update");
        throw e;
    }
}