如何捕获异步非承诺错误? (对特定错误做出反应)
Posted
技术标签:
【中文标题】如何捕获异步非承诺错误? (对特定错误做出反应)【英文标题】:How can I catch asynchronous-non-promised errors ? ( react to that specific error) 【发布时间】:2018-05-28 06:37:11 【问题描述】:我知道那里有答案,但我没有找到针对我的实际问题的具体答案。
目前我use下面的模式很多:
class A
getLocation()
return Promise.reject(2222222)
async a()
try
var loc = await this.getLocation();
alert(loc)
catch (e)
alert("catch 2")
new A().a();
结果:“catch 2”
如果我在getLocation
中抛出错误:
getLocation()
throw Error("ffffff")
- 我得到相同的结果 - 没关系。
那么问题出在哪里?
如您所知,asynchronously-non-promised
引发的错误是另一头野兽:
所以this code won't be catched:
getLocation() //bad code from a third party code , third party code
return new Promise((v, x) => setTimeout(() =>
throw Error("ffffff")
, 100))
问题:
关于我想捕捉错误的事实 - 是否有更好的模式来捕捉这个?
当然可以:
window.onerror = function () alert(4)
但这不符合 .catch(...)
或 catch()
的流程,我将无法针对导致错误的那个特定操作执行操作。
全面披露: 没有真实的生活场景。学习目的。
【问题讨论】:
【参考方案1】:应该在错误发生的地方发现错误。
这种代码代码不正确,应该就地修复:
getLocation() //bad code from a third party code
return new Promise((v, x) => setTimeout(() =>
throw Error("ffffff")
, 100))
如果这是第三方代码,可以分叉或修补。
正如问题已经提到的那样,onerror
可以全局跟踪异常。这应该只用于通知开发人员存在的错误,而不是以正常方式处理它们。
unhandledrejection
事件可用于相同目的来通知承诺中未处理的拒绝。它将无法处理上面截图中的错误,因为它被抛出在 setTimeout
回调中并且不会导致 promise 被拒绝。
【讨论】:
【参考方案2】:我猜基本用法是这样的:
class A
getLocation(x)
return new Promise((resolve, reject) => setTimeout(() =>
// a lot of async code
try
//simulate unexpected exception
if (x === 2)
throw ("code error");
if (x)
resolve('success');
else
reject('conditional rejection');
catch (ex)
reject(ex);
, 1000));
async a(x)
await this.getLocation(x).then((loc) => console.info(loc)).catch((e) => console.error(e));
let o = new A();
o.a(2);
o.a(0);
o.a(1);
Promise
的拒绝不一定是代码 Exception
,代码 Exception
也不一定会触发 Promise
拒绝。
【讨论】:
【参考方案3】:异步抛出的错误是一个不同的野兽
是的。并且必须不惜一切代价避免它。因此,永远不要将业务代码(包括属性访问等琐碎的事情)放在异步的非承诺回调中。它可以扔!很明显,JSON.parse
可能会失败,当“对象”是 null
或 undefined
或涉及 getter 时,属性访问可能会抛出,或者循环可能会在本应发生的事情时失败一个数组没有.length
。
唯一允许作为异步非承诺回调的是 resolve
、reject
和 (err, res) => if (err) reject(err); else resolve(res);
(对于具有多个参数的怪异 API,可能是可变参数版本)。
所以把不好的代码改写成
async getLocation()
await new Promise(resolve => setTimeout(resolve, 100));
throw Error("ffffff");
或
getLocation()
return new Promise(resolve => setTimeout(resolve, 100)).then(res =>
throw Error("ffffff");
);
当它是第三方代码让他们修复它时,对您的修复提出上游合并请求,或者如果这些不起作用则放弃该方。
有没有更好的模式来捕捉这个?
好吧,domains(在节点中)本应解决异步(未捕获)异常的非局部性问题,但they didn't work out。也许有一天,拥有更好的母语支持的zones 会取代它们。
【讨论】:
以上是关于如何捕获异步非承诺错误? (对特定错误做出反应)的主要内容,如果未能解决你的问题,请参考以下文章
如何解决反应身份验证中的未捕获(承诺中)TypeError?