await js 报错_await的错误处理问题,一个issue引发的ts社区的讨论

前提

大家都知道try-catch对异步流程中的错误有时候是捕捉不到的,eg:

function func1() {

try {

func2();

} catch (error) {

console.log('error');

}

}

function func2() {

setTimeout(() => {

throw new Error('error')

}, 1000)

}

func1();

执行这些代码,你会发现过了一秒后程序直接报错,console.log('error')并没有执行,也就是func1并没有捕捉到func2的异常。这就是异步的问题所在。

我们一般的做法就是直接加上async/await:

async function func1() {

try {

await func2();

} catch (error) {

console.log('error');

}

}

function func2() {

return new Promise((resolve, reject) => {

setTimeout(() => {

reject()

}, 1000)

})

}

func1();

func2被Promise封装,reject后会被func1的try-catch捕获到,像现在的axios很多库都已经封装好Promise方便直接await。

问题

这里我们要讨论的就是对await到底用try-catch,if(err)的方式。

if(err)的方式在node中的很多异步回调函数中很多场景都用到,err永远是node结果回调函数的第一个参数,但此情景又与node中的不一样。对await的错误处理要想获取到err,需要额外增加一个函数,用try-catch捕获到的err return出去。

eg:

每次使用都要引用errCatch()。

async function errCatch(asyncFunc) {

try {

let res = await asyncFunc();

retrun [null, res]

} catch (error) {

return [error,null];

}

}

这样func1就要写成:

async function func1() {

let [err, res] = errCatch(asyncFunc);

if (err) {

//.....

}

}

那么这种写法比直接try-catch有什么好处,第一点就是更加语义化了,这个问题在deno社区就这个问题的ts写法引起过讨论,可以看看这个issue:

第一个意思是 Golang 只需要处理 return 出来的错误,很少有运行时错误,即便有,也是可以在 defer 统一处理。 第二个意思是,像一个读流 copy 到另一个写流。假如因为某个异常中断的话,我们需要知道是读取到了第 n 的细节中断的,然后错误是什么。这样的场景就适合这样使用。(具体可以再copy中实现)

(但我觉得这个其实是特殊场景,用try-catch也能控制)

其实一个老哥也指出传统的promise做法,因为await的错误不捕获会导致整个async函数的中断,用catch也能避免中断并捕捉到错误。

开issue的作者是说使用这种style的原因是这样的:

最后维护者是这么说的:

大概意思就是说

“我们可以在utils/async.ts中实现这一点,供我们自己使用,并作为用户的一个选项提供。但正如我所说,在更多的情况下,Try-Catch是进入JS的正确方法,或者提供像上面提到的@J-F1这样的catch处理程序。

(作为一个夸张的例子,C中的全局errno在某些情况下可能更干净,但是我们在JS中不做这样的构造,因为它违背了预期的语言用法。

如果您认为这些助手非常有用,那么如果您能够贡献并提交一个pr来将它们添加到utils/async.ts中,这将是非常好的,并且有可能在将来说服更多的JS开发人员尝试这样的处理方式,这样有一天它就足够惯用了。

(我目前受到一些法律纠纷的约束,因此不幸的是,我自己做不到。)”

其实上面issue作者举的那个例子就是说在官方库中有些错误不用被处理,只是做检测的情况下,不用写try-catch,catch的e就更不用写上了,用了helper的style后,可以直接这样写:

const statInfo = await maybe(stat(fn)); // yields FileInfo | null

const mode = statInfo ? statInfo.mode : null;

看上去更加舒服???

知乎上关于node.js 应该 return new Error() 还是 throw new Error()的讨论

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值