javascript - 每个 Promise-chain -> try/catch/await 指南都在教导危险的约定吗?
问题描述
我见过的从捕获错误的 Promise 链到 try/catch/await 的每个示例都如下所示:
class Api {
static getUserPhones(userObj) {
console.log(userObj.phones.length)
return new Promise((resolve, reject) => reject('err'))
}
}
const user = { id: 123, phones: [] }
/** Turn this... */
Api.getUserPhones(user.id) // user.id is a mistake
.then(resp => console.log(resp))
.catch(err => console.error('network error:', err))
/** ...into this! */
try {
const resp = await Api.getUserPhones(user.id) // user.id is a mistake
console.log(resp)
} catch (err) {
console.error('network error:', err)
}
但这在最坏的情况下是不安全的,并且充其量是为我们设置错误。任何可能发生在传递给它的参数 ( ) 内或什至中的任何TypeError
, ReferenceError
, SyntaxError
,等都会意外地被吞入块中。除非您的代码始终没有错误,否则将您的代码转换为与示例类似的代码可能会使查找错误和调试它们变得非常具有挑战性。RangeError
Api.getUser()
user.wrong.id
try
try/catch
举个极端的例子,如果指南告诉我们将您的所有代码放在一个try
. 一切都可以抛出,即使不是设计为,我们应该只try
在我们的代码按设计抛出时使用。
我错过了什么吗?每个人都只是在编写风险更高的代码而不自知吗?
解决方案
两个代码片段在行为上并不总是 100% 相同的事实并不会使它们中的任何一个都不安全。它只是使它们在特定的边缘情况下有所不同。最后,作为代码作者,是否需要保留这种边缘情况是您的决定。
也就是说,适当的等价物只会在 try/catch 之外获得承诺:
const promise = Api.getUser(user.id)
try {
const resp = await promise
console.log(resp)
} catch (err) {
console.error(err)
}
但是,从这里我们可以根据我们可以做出的假设进行一些修改。例如,如果我们知道它Api.getUser(user.id)
不会抛出,那么Api.getUser(user.id)
在try
块内调用是完全有效的。
作为未成年人,我还想就这个问题发表评论:
假设 Api.getUser() 中的所有内容都将永远不会出现 javascript 错误,这是非常愚蠢的
这是一个强有力的断言,它也恰好是明显错误的。首先,让我们明确一点,并非内部的所有内容都Api.getUser()
需要没有错误。只要Api.getUser()
在调用者内部处理了任何错误,就仍然可以免于处理这些错误。其次,如果Api.getUser()
有文件证明不扔,那么期望它不扔是一件非常合理的事情。否则,你必须做出判断,不管它是否可以抛出,以及这些错误是否需要与通过 Promise 传播的错误有任何不同的处理。
推荐阅读
- regex - 当我按顺序编写条件时,为什么这个正则表达式不接受?
- node.js - Node.js 路由发送到不正确的控制器
- c++ - 使用 C++ 对数组进行排序时的 SIGSEGV
- python - 找不到 Python Visual Studio 代码模块
- swift - 如何使用协议关联类型在 Swift 中编写泛型函数
- python - PermissionError: [Errno 13] 权限被拒绝失败
- react-native - 有没有办法向 Square Reader SDK Checkout Flow 添加订单 ID?
- c - 为什么这个程序在 ubuntu windows 桌面应用程序和 ubuntu 虚拟盒上给出不同的输出?
- reactjs - 选择正确的枚举类型来访问对象嵌套属性
- python - 谷歌云功能使用python将源桶的所有数据复制到另一个桶