首页 > 解决方案 > 在 JavaScript 中使用 Promise 实现快速失败的设计

问题描述

我不确定“快速失败”是否是描述这种方法的最佳方式,但自从我开始学习编程以来,我一直被教导设计这样的功能:

function doSomething() {
    ... // do error-prone work here

    if (!allGood) {
        // Report error, cleanup and return immediately. Makes for cleaner,
        // clearer code where error-handling is easily seen at the top
        ...
        return;
    }

    // Success! Continue on with (potentially long and ugly) code that may distract from the error
}

因此,我试图像这样调用一个承诺函数:

doSomethingAsync(param).catch(err => {
    console.error(err);
}).then(() => {
    // Continue on with the rest of the code
});

但这给了我类似于finally经典try...catch...finally语句块的行为,即该then()块将始终被调用,即使在错误之后也是如此。有时这很有用,但我很少发现自己需要这样的功能(或try...catch一般的陈述,就此而言)。

因此,为了尽可能快速和清晰地失败,有没有一种方法可以使上面的第二个示例以我期望的方式工作(即then()catch()在没有执行的情况下执行,但单个catch()仍然会捕获所有错误由doSomethingAsync()) 提出?

标签: javascriptpromisees6-promisefail-fast

解决方案


如果使用asyncandawait而不是.then,则可以有效地等待 Promise 解决(或拒绝),如果它拒绝,则提前返回:

(async () => {
  try {
    await doSomethingAsync(param);
  } catch(err) {
    console.error(err);
    return;
  }
  // Continue on with the rest of the code
})();

const doSomethingAsync = () => new Promise((resolve, reject) => Math.random() < 0.5 ? resolve() : reject('bad'));

(async () => {
  try {
    await doSomethingAsync();
  } catch(err) {
    console.error(err);
    return;
  }
  console.log('continuing');
})();

那是我更喜欢的。您也可以使用该.then(onResolve, onReject)技术,但通常不建议这样做:

function onReject(err) {
  console.log(err);
};
doSomethingAsync(param).then(onResolve, onReject);
function onResolve() {
  // Continue on with the rest of the code
}

const doSomethingAsync = () => new Promise((resolve, reject) => Math.random() < 0.5 ? resolve() : reject('bad'));

function onReject(err) {
  console.log(err);
};
doSomethingAsync().then(onResolve, onReject);
function onResolve() {
  console.log('continuing');
}

这将onReject 处理由doSomethingAsync(param). 如果你onResolve也可以把它扔进它的体内,那么你将不得不将另一个链接.catch到它上面(这会开始看起来有点乱 - 通常只在一个地方捕获错误会更好)


推荐阅读