javascript - 防止 “Uncaught (in promise)” 警告。如何避免 'catch' block ? ES6 Promise 与 Q Promise

标签 javascript ecmascript-6 promise es6-promise q

我的问题由两部分组成:

第 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 use api 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/

相关文章:

javascript - 用数组元素替换字符串键

javascript - 如何访问 next .then() 中的日期 - 获取 api

javascript - 导入对象未定义

javascript - 如何从 AngularJS 中的异步树结构 API 创建 promise

javascript - 我应该模拟 '.$promise' 对象吗?

javascript - 从 jquery 数据表中获取特定的行数据

JavaScript Element.requestFullscreen() 未定义

javascript - 增加 onclick 类 javascript

javascript - 在 React 中测试嵌套组件回调

javascript - 为什么在使用文字字符串和局部变量时我的结果不同