简体   繁体   English

防止“Uncaught (in promise)”警告。 如何避免'catch'块? ES6 承诺与 Q 承诺

[英]Prevent of “Uncaught (in promise)” warning. How to avoid of 'catch' block? ES6 promises vs Q promises

My question consist of two parts:我的问题由两部分组成:

Part 1第1部分

According to standard ES6 Promise I see that I forced to use catch block everywhere, but it looks like copy/paste and looks weird.根据标准的 ES6 Promise我看到我被迫到处使用catch块,但它看起来像复制/粘贴,看起来很奇怪。

Example:例子:

I have some class which makes request to backend (lets call it API class).我有一些类向后端发出请求(我们称之为API类)。

And I have a few requirements for API class using:我对API类有一些要求:

1) I need to make requests in different parts of my application with single request errors processing: 1)我需要在我的应用程序的不同部分发出请求,并处理单个请求错误:

// somewhere...
api.getUser().then(... some logic ...);

// somewhere in another module and in another part of app...
api.getUser().then(... some another logic...); 

2) I want so 'then' blocks would work ONLY when 'getUsers' succeeded. 2)我希望“then”块仅在“getUsers”成功时才起作用。

3) I don't want to write catch block everywhere I use api.getUsers() 3)我不想在所有使用api.getUsers()地方写catch

api.getUser()
// I don't want following
.catch(e => {
    showAlert('request failed');
})

So I'm trying to implement single error processing inside of the class for all "users requests"所以我试图在类内部为所有“用户请求”实现单个错误处理

class API {
    getUser() {
        let promise = makeRequestToGetUser();
        promise.catch(e => {
            showAlert('request failed');
        });
        return promise;
    }
}

...but if request fails I still forced to use catch block ...但如果请求失败,我仍然被迫使用catch

api.getUser()
    .then(... some logic...)
    .catch(() => {}) // <- I forced to write it to avoid of “Uncaught (in promise)” warning

... otherwise I'll get “Uncaught (in promise)” warning in console. ...否则我会在控制台中收到“Uncaught (in promise)”警告。 So I don't know the way of how to avoid of .catch block everywhere I use api instance.所以我不知道如何在我使用api实例的任何地方避免.catch块。

Seems this comes from throwing error in such code:似乎这来自在这样的代码中抛出错误:

// This cause "Uncaught error"
Promise.reject('some value').then(() => {});

May be you can say 'just return in your class "catched" promise'.也许你可以说'刚刚回到你的班级“抓住”了承诺'。

class API {
    getUser() {
        return makeRequestToGetUser().catch(e => {
            showAlert('request failed');
            return ... 
        });
    }
}

...but this contradict to my #2 requirement. ...但这与我的#2要求相矛盾。

See this demo: https://stackblitz.com/edit/promises-catch-block-question看这个演示: https : //stackblitz.com/edit/promises-catch-block-question

So my 1st question is how to implement described logic without writing catch block everywhere I use api call?所以我的第一个问题是如何在我使用api调用的任何地方都不catch块的情况下实现所描述的逻辑?

Part 2第2部分

I checked if the same API class implementation with Q library will get the same result and was surprised because I don't get “Uncaught (in promise)” warning .我检查了与Q库相同的API类实现是否会得到相同的结果并感到惊讶,因为我没有收到“Uncaught (in promise)” warning BTW it is more expectable behavior than behavior of native ES6 Promises.顺便说一句,它比原生 ES6 Promises 的行为更值得期待。

In this page https://promisesaplus.com/implementations I found that Q library is implementation of Promises/A+ spec.在这个页面https://promisesaplus.com/implementations我发现Q库是 Promises/A+ 规范的实现。 But why does it have different behavior?但为什么它有不同的行为? Does es6 promise respects Promises/A+ spec? es6 promise 是否尊重 Promises/A+ 规范?

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?任何人都可以解释为什么这些库具有不同的行为,哪个是正确的,以及如果“ES6 Promises implementation”正确,如何实现提到的逻辑?

I see that I forced to use catch block everywhere我看到我被迫到处使用 catch 块

No, you don't need to do that.不,你不需要这样做。 Instead, return the promise created by then to the caller (and to that caller's caller, and...).相反,then创建的承诺返回给调用者(以及该调用者的调用者,以及......)。 Handle errors at the uppermost level available (for instance, the event handler that started the call sequence).在可用的最高级别处理错误(例如,启动调用序列的事件处理程序)。

If that's still too many catch s for you, you can hook the unhandledrejection event and prevent its default:如果这对您来说仍然太多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"));

The browser will trigger that event prior to reporting the unhandled rejection in the console.浏览器将在控制台中报告未处理的拒绝之前触发该事件。

Node.js supports this as well, on the process object: Node.js 在process对象上也支持这一点:

process.on('unhandledRejection', error => {
  // `error` is the rejection reason
});

Note that you get the reason directly rather than as a property of an event object.请注意,您可以直接获得原因,而不是作为事件对象的属性。

So I don't know the way of how to avoid of .catch block everywhere I use api instance.所以我不知道如何在我使用api实例的任何地方避免.catch块。

Surely the caller of getUser needs to know it failed?肯定getUser的调用者需要知道它失败了? I mean, if the answer to that is really "no, they don't" then the event is the way to go, but really the code using api should look like this:我的意思是,如果答案真的是“不,他们没有”,那么事件就是要走的路,但实际上使用api的代码应该是这样的:

function useTheAPI() {
    return getUser()
        .then(user => {
            // Do something with user
        });
}

(or the async equivalent) so that the code calling useTheAPI knows that an error occurred; (或async等效项)以便调用useTheAPI的代码知道发生了错误; again, only the top-level needs to actually handle the error.同样,只有顶级需要实际处理错误。

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?任何人都可以解释为什么这些库具有不同的行为,哪个是正确的,以及如果“ES6 Promises implementation”正确,如何实现提到的逻辑?

Both are correct.两者都是正确的。 Reporting unhandled exceptions entirely in userland (where libraries live) is hard-to-impossible to do such that there aren't false positives.完全在用户空间(图书馆所在的地方)报告未处理的异常是很难做到的,这样就不会有误报。 JavaScript engines can do it as part of their garbage collection (eg: if nothing has a reference to the promise anymore, and it was rejected, and nothing handled that rejection, issue the warning). JavaScript 引擎可以将其作为垃圾收集的一部分来执行(例如:如果不再有对 promise 的引用,并且它被拒绝,并且没有任何处理该拒绝,则发出警告)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM