【问题标题】:Why would you try-catch around a promise? Does that catch the promise's error?你为什么要试图抓住一个承诺?这能捕捉到承诺的错误吗?
【发布时间】:2017-09-27 20:55:20
【问题描述】:

我偶然发现了一些对我来说很奇怪的代码:

try {
  somePromise()
    .then(res => console.log(res));
} catch (err) {
  console.error(err);
}

如果某些somePromise() 失败,这不会被捕获,应用程序会崩溃吗?这个 try-catch 有什么作用吗?

应该是这样,对吗?:

  somePromise()
    .then(res => console.log(res))
    .catch(err => console.error(err));

【问题讨论】:

  • 这确实看起来不对。
  • somePromise() 仍然可能引发错误。
  • @FelixKling 所以你说的 try-catch 仍然会崩溃,因为没有真正处理承诺错误?
  • 我只是说在 somePromise 内部,在返回 promise 之前可能会抛出错误。
  • 你是对的。 “未声明不是例外”是错误的。我混淆了关于 es6 和 v8/node 的想法。 Common JS 实际上将其捕获为运行时错误。

标签: javascript ecmascript-6 promise es6-promise


【解决方案1】:

TL;DR - 如果返回 Promise 的函数在返回 Promise 之前抛出异常,则必须在常规 try-catch 块中捕获该异常。

考虑这个函数

function asyncAdd(x,y){
   if(x === 2){
        throw new Error("good old exception")
   }else if(x === 1) { 
      return Promise.reject("fancy exception")
   }

   return Promise.resolve(x+y)
}

这将打印“尝试捕获旧异常”

try{
  asyncAdd(2,10).then(x =>console.log("result", x)).catch(y => console.error("Promise caught", y));
}catch (e){
  console.error("Try caught", e);
}

这将打印“Promise 捕捉到奇特的异常”

try{
  asyncAdd(1,10).then(x =>console.log("result", x)).catch(y => console.error("Promise caught", y));
}catch (e){
  console.error("Try caught", e);
}

【讨论】:

  • 我可能会补充一点,不应该创建自己的代码,既可以抛出又可以返回一个承诺。尽管您可能必须防止其他人的代码这样做,但您不应允许自己的代码这样做,因为它创建的代码很难安全使用。
【解决方案2】:

如果你正在处理一个可能返回 Promise 抛出错误的垃圾函数,那真的很不幸。我会推荐一个通用的tryCatch 实用程序,如下所示来处理攻击性功能。

const badFunction = x =>
{ if (x)
    return Promise.resolve(x)
  else
    throw Error('this is a bad function')
}

const tryCatch = (f, ...args) =>
  new Promise(r => r(f(...args)))

tryCatch(badFunction, 1)
  .then(console.log, console.error)
// 1

tryCatch(badFunction, 0)
  .then(console.log, console.error)
// Error: this is a bad function

如果可以,请修复它

如果垃圾功能在你的控制下修复,那么我建议你写这样的东西

const goodFunction = x =>
{ if (x)
    return Promise.resolve(x)
  else
    return Promise.reject(Error('this is a good function'))
}

goodFunction(1).then(console.log, console.error)
// 1

goodFunction(0).then(console.log, console.error)
// Error: this is a good function

.then-chained 函数中未捕获的错误

这并不是说有时我们仍然可能会遇到需要使用可能抛出的函数的情况。例如,如果我们then 一个可以抛出的函数——在这种情况下是JSON.parse——Promise 已经具备了以一种方便的方式处理这个问题;抛出的错误将在被拒绝的承诺中捕获

const goodFunction = x =>
  Promise.resolve(x)
  
goodFunction('"abc"')
  .then(JSON.parse)
  .then(console.log, console.error)
  // 'abc'

goodFunction('abc')
  .then(JSON.parse)
  .then(console.log, console.error)
  // 'Unexpected token a in JSON at position 0'

Promise 执行器中未捕获的错误

如果一个函数在你的 Promise 执行器中抛出一个错误,别担心,这个错误将包含在一个自动拒绝的 Promise 中 -

const okFunction = x =>
  new Promise(resolve => resolve(JSON.parse(x)))

okFunction('"abc"').then(console.log, console.error)
// 'abc'

okFunction('abc').then(console.log, console.error)
// Error: Unexpected token a in JSON at position 0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-25
    • 1970-01-01
    • 1970-01-01
    • 2017-03-15
    • 2020-06-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多