javascript - 防止“未捕获(承诺)”警告。如何避免'catch'块?ES6 承诺与 Q 承诺
问题描述
我的问题包括两部分:
第1部分
根据标准 ES6 Promise
,我看到我被迫在catch
任何地方使用块,但它看起来像复制/粘贴并且看起来很奇怪。
例子:
我有一些类向后端发出请求(我们称之为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' 块仅在'getUsers' 成功时才起作用。
3)我不想catch
在我使用的任何地方写块api.getUsers()
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
块
api.getUser()
.then(... some logic...)
.catch(() => {}) // <- I forced to write it to avoid of “Uncaught (in promise)” warning
...否则我会在控制台中收到“Uncaught (in promise)”警告。所以我不知道如何在我使用实例的.catch
任何地方避免阻塞的方式。api
似乎这来自在这样的代码中抛出错误:
// This cause "Uncaught error"
Promise.reject('some value').then(() => {});
也许你可以说'只是回到你的班级'抓住'承诺'。
class API {
getUser() {
return makeRequestToGetUser().catch(e => {
showAlert('request failed');
return ...
});
}
}
...但这与我的#2要求相矛盾。
请参阅此演示:https ://stackblitz.com/edit/promises-catch-block-question
所以我的第一个问题是如何实现所描述的逻辑而不在我使用调用的catch
任何地方编写块?api
第2部分
我检查了API
与库相同的类实现是否Q
会得到相同的结果,并且很惊讶,因为我没有得到“Uncaught (in promise)” warning
. 顺便说一句,它比原生 ES6 Promises 的行为更值得期待。
在此页面https://promisesaplus.com/implementations我发现该Q
库是 Promises/A+ 规范的实现。但是为什么它有不同的行为呢?es6 promise 是否尊重 Promises/A+ 规范?
谁能解释为什么这些库有不同的行为,哪个是正确的,以及如果“ES6 Promises implementation”正确,如何实现上述逻辑?
解决方案
我看到我被迫到处使用 catch 块
不,你不需要这样做。相反,将由创建的承诺返回then
给调用者(以及该调用者的调用者,并且......)。在可用的最高级别处理错误(例如,启动调用序列的事件处理程序)。
如果这对您来说仍然太多catch
,您可以挂钩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"));
浏览器将在控制台中报告未处理的拒绝之前触发该事件。
process
Node.js 在对象上也支持这一点:
process.on('unhandledRejection', error => {
// `error` is the rejection reason
});
请注意,您可以直接获取原因,而不是作为事件对象的属性。
所以我不知道如何在我使用实例的
.catch
任何地方避免阻塞的方式。api
当然getUser
需要知道它的调用者失败了?我的意思是,如果答案真的是“不,他们没有”,那么事件就是要走的路,但实际上使用的代码api
应该如下所示:
function useTheAPI() {
return getUser()
.then(user => {
// Do something with user
});
}
(或async
等价物)以便代码调用useTheAPI
知道发生了错误;同样,只有顶层需要实际处理错误。
谁能解释为什么这些库有不同的行为,哪个是正确的,以及如果“ES6 Promises implementation”正确,如何实现上述逻辑?
两者都是正确的。完全在用户区(图书馆所在的地方)报告未处理的异常很难做到没有误报。JavaScript 引擎可以将其作为其垃圾收集的一部分来执行(例如:如果没有任何东西对 promise 的引用,并且它被拒绝,并且没有任何处理该拒绝,则发出警告)。
推荐阅读
- angular - 如何在 Typescript 中动态禁用或启用 ng-multiselect-dropdown
- python - sqlalchemy 等价于 sql 语法
- php - 在路由组中分配中间件和在控制器的构造函数中启动它有什么区别吗?
- php - 使用imagick从PDF创建图像时出现以下错误,任何人都可以帮助修复它
- javascript - webpack 4 给出背景: url([object Module]) as bg image
- jasmine - Uncaught ReferenceError: Zone is not defined (Jasmine)
- c# - 有没有办法用 linq 查询过滤嵌套列表,以便我最终得到充分过滤列表的过滤列表?
- google-cloud-platform - 在 dataproc 上提交 Presto 作业
- c# - Perlin 噪声波对 3d 球体的影响
- android - Android Gradle 插件警告:字符串 'ucrop_error_input_data_is_absent' 没有默认翻译