我的问题由两部分组成:
第 1 部分
根据标准 ES6 Promise
我发现我被迫在任何地方使用 catch
block ,但它看起来像复制/粘贴,看起来很奇怪。
示例:
我有一些向后端发出请求的类(我们称之为API
类)。
我对使用 API
类有一些要求:
1) 我需要在应用程序的不同部分发出请求,并处理单个请求错误:
// somewhere...
api.getUser().then(... some logic ...);
// somewhere in another module and in another part of app...
api.getUser().then(... some another logic...);
2) 我希望“then” block 仅在“getUsers”成功时才起作用。
3) 我不想在使用 api.getUsers()
的任何地方编写 catch
block
api.getUser()
// I don't want following
.catch(e => {
showAlert('request failed');
})
所以我试图在类内部为所有“用户请求”实现单个错误处理
class API {
getUser() {
let promise = makeRequestToGetUser();
promise.catch(e => {
showAlert('request failed');
});
return promise;
}
}
...但是如果请求失败我仍然被迫使用 catch
block
api.getUser()
.then(... some logic...)
.catch(() => {}) // <- I forced to write it to avoid of “Uncaught (in promise)” warning
...否则我会在控制台中收到“未捕获( promise )”警告。所以我不知道如何在使用 api
实例的地方避免 .catch
block 。
这似乎是由于在此类代码中抛出错误造成的:
// This cause "Uncaught error"
Promise.reject('some value').then(() => {});
也许你可以说“只要回到你的类(class)“捕获” promise 即可”。
class API {
getUser() {
return makeRequestToGetUser().catch(e => {
showAlert('request failed');
return ...
});
}
}
...但这与我的#2要求相矛盾。
查看此演示:https://stackblitz.com/edit/promises-catch-block-question
所以我的第一个问题是如何实现所描述的逻辑,而无需在使用 api
调用的地方编写 catch
block ?
第 2 部分
我检查了使用 Q
库的相同 API
类实现是否会得到相同的结果,并且感到惊讶,因为我没有得到“未捕获( promise )”警告
。顺便说一句,它是比原生 ES6 Promise 的行为更可预期的行为。
在此页面https://promisesaplus.com/implementations我发现 Q
库是 Promises/A+ 规范的实现。但为什么它有不同的行为呢?
es6 Promise 是否尊重 Promises/A+ 规范?
任何人都可以解释为什么这些库有不同的行为,哪一个是正确的,以及如果“ES6 Promises 实现”正确的话如何实现提到的逻辑?
最佳答案
I see that I forced to use catch block everywhere
不,您不需要这样做。相反,将 then
创建的 Promise 返回给调用者(以及该调用者的调用者,以及……)。在可用的最高级别处理错误(例如,启动调用序列的事件处理程序)。
如果这对您来说仍然太多 catch
,您可以 Hook unhandledrejection
事件并阻止其默认值:
window.addEventListener('unhandledrejection', event => {
event.preventDefault();
// You can use `event.reason` here for the rejection reason, and
// `event.promise` for the promise that was rejected
console.log(`Suppressed the rejection '${event.reason.message}'`);
});
Promise.reject(new Error("Something went wrong"));
浏览器将在控制台中报告未处理的拒绝之前触发该事件。
Node.js 在 process
对象上也支持此功能:
process.on('unhandledRejection', error => {
// `error` is the rejection reason
});
请注意,您可以直接获取原因,而不是作为事件对象的属性。
So I don't know the way of how to avoid of
.catch
block everywhere I useapi
instance.
getUser
的调用者肯定需要知道它失败了吗?我的意思是,如果答案确实是“不,他们不”,那么事件就是正确的选择,但实际上使用 api
的代码应该如下所示:
function useTheAPI() {
return getUser()
.then(user => {
// Do something with user
});
}
(或等效的async
),以便调用useTheAPI
的代码知道发生了错误;同样,只有顶层需要实际处理错误。
Can anybody explain why these libraries has different behavior, which one is correct, and how implement mentioned logic in case if "ES6 Promises implementation" is correct?
两者都是正确的。完全在用户空间(库所在的地方)报告未处理的异常很难做到不出现误报。 JavaScript 引擎可以将其作为垃圾收集的一部分(例如:如果不再有任何内容引用 Promise,并且它被拒绝,并且没有任何内容处理该拒绝,则发出警告)。
关于javascript - 防止 “Uncaught (in promise)” 警告。如何避免 'catch' block ? ES6 Promise 与 Q Promise,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53505159/