异步函数的 neverthrow 有什么意义?

What is the point of neverthrow for async functions?

起初我在整个 typescript/node 应用程序中使用了 throw 和 catch 之后,我偶然发现了 neverthrow(https://www.npmjs.com/package/neverthrow).

我在编写我的第一个更大的应用程序和打字稿时才意识到缺少将函数标记为抛出的能力实际上是一个多么大的问题。

neverthrow 或其他基于任一的解决方案似乎都很好。对于我的非异步函数,我已经将所有内容更改为 neverthrow。

我真的不明白为什么我应该费心将所有异步函数包装到 return ResultAsync。任何异步函数都被标记为本质上可能会抛出错误(因为它们 return 一个 Promise),或者我错了吗? 我是否遗漏了任何一点,我确实应该更改所有异步函数以使用 ResultAsync?

使用 ResultAsync<T, E> 类型而不是 Promise<T> 类型没有什么好处。

从类型本身可以看出,前一个选项有一个E泛型参数,表示结果可能包含的错误类型。这是非常有益的,因为您可以独立处理每种错误类型,而不是捕获一般错误实例。以 HTMLImageElement.decode 为例;它 return 是一个可能会抛出 EncodingError 的 promise,但如果不检查文档,您将不会知道这一点。

另一个好处来自被迫处理潜在的错误结果。 Javascript 错误未经检查,这意味着没有编译器或解释器来确保您始终将 await promise 包装在 try-catch 中。另一方面,当您 await result 时,您必须检查它是否产生结果 (result.isOk() === true) 或抛出错误 (result.isErr() === true)。这意味着每次您想要解包(从 Result<T, _> 获取 T)结果时,您都必须处理潜在的错误情况。从理论上讲,这会产生更健壮和故障安全的代码。

结果并非没有缺点。 Javascript 生态系统已采用 Promises 作为异步处理 return 事物的标准方式,因此 ResultAsync 可能无法在任何 Promise 会工作的地方工作。此外,每次要解包结果时都必须处理潜在的错误结果,这会使代码更加冗长。

如果您主要处理在同一个项目中编写的异步代码,并且认为您可以从更多故障安全代码中受益,那么在您使用 [=21] 的任何地方使用 ResultAsync 可能是有意义的=].