【问题标题】:Why does a chained promise's .then() runs after the prior promise failed with .catch()? [duplicate]为什么链式 Promise 的 .then() 在先前的 Promise 因 .catch() 失败后运行? [复制]
【发布时间】:2021-10-17 07:46:40
【问题描述】:

我有三个函数functionAfunctionBfunctionC

为什么functionC 中的.then(id)... 块会运行,即使functionB 抛出错误并以catch 语句结束。

我确定我错过了关于承诺的重要内容。

    const functionA = () => {
      return fetch("http://localhost:3001/types")
        .then((response) => response.json())
        .then((data) => data)
        .catch((error) => error);
    };

    const functionB = (type) => {
      return functionA()
        .then((response) => response.filter((item) => item.name === type))
        .then((result) => {
          if (result.length !== 1) { // assume for this example this is truthy
            const error = new Error("no type found or found more than one");
            throw error;
          } else {
            return result[0].id;
          }
        })
        .catch((error) => error); // this runs as expected since we're throwing an error above
    };
    

    const functionC = (x, y) => {                
      return functionB(y)
        .then((id) => { //why does this block run? 
          
                       //..do something
                      })
           
        .catch((error) => console.log("functionB threw an error"));
    };

【问题讨论】:

  • 正是因为您已经捕获错误,这使得链能够成功继续。
  • 旁注:.then((data) => data) 从来没有任何理由。它只是引入了一个额外的异步分辨率,而没有改变任何东西。

标签: javascript promise


【解决方案1】:

您的catch 处理程序使用error 值将拒绝转换为履行。只需完全删除.catch((error) => error);,这样拒绝就会传播给调用者。

这个(基本上就是你所拥有的,只是分散在两个函数中):

doSomething()
.then(x => { /* ...do something with x...*/ })
.catch(error => error)
.then(y => { /* ...do something with y...*/ });

大致类似于这个同步代码:

let y;
try {
    const x = doSomething();
    y = /* ...do something with x... */;
} catch (error) {
    y = error;
}
/* ...do something with y... */;

捕获错误然后正常完成会抑制错误。

一般来说,使用 Promise 的非async 代码应该做以下两件事之一:

  1. 在本地处理错误 - 这通常只是顶级入口点,例如您的主函数(如果有的话)或事件处理程序。

  2. 使用catch 返回调用then 的结果不使用,这样拒绝就会传播到最外层(希望由于上面的#1 而被处理)。 p>

仅供参考,这基本上就是 async/await 自动为您所做的(忽略很多细节)。只是为了它的价值,这是使用async/await 的代码(稍作修改),假设functionC 是应处理错误的顶级入口点:

const functionA = async () => {
    const response = await fetch("http://localhost:3001/types");
    if (!response.ok) { // (You're missing this check)
        throw new Error(`HTTP error ${response.status}`);
    }
    return response.json();
};

const functionB = async (type) => {
    const result = (await functionA()).filter(item => item.name === type);
    if (result.length !== 1) {
        const error = new Error("no type found or found more than one");
        throw error;
    }
    return result[0].id;
};

const functionC = async (x, y) => {
    // I'm assuming this is your top-level entry point, so we'll handle
    // errors here
    try {
        const id = await functionB(y);
        //..do something
    } catch (error) {
        console.log("functionB threw an error");
    }
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-18
    • 2021-03-08
    • 2016-10-29
    • 2020-07-13
    • 1970-01-01
    • 2021-07-05
    • 1970-01-01
    相关资源
    最近更新 更多