Rejecting a raw promise in asynchronous mode promises

I use Oboe.js to parse a really very large JSON file

const promises = []; oboe('http://domain/my-file.js') .node('items.*', item => { // parseItem() returns a rejected Promise because of invalid JSON items promises.push(parseItem(item)); }) .done(() => { Promise.all(promises).then(() => { doSomething(); }); }) 

But my browser console is flooded with Uncaught (in promise) . The same thing happens if you write a promise in setTimeout() as

 const promises = []; setTimeout(() => { promises.push(Promise.reject()); }, 500); // some time in the future Promise.all(promises); 

Which is really strange: modern browsers behave differently. In Firefox Developer Edition, everything works without error messages, and in Chrome, Uncaught (in promise) floods me. In Chrome, you get a message instantly if you write Promise.reject(); without a catch. In Firefox and Safari, nothing happens.

So what is the solution for this? Ignoring the message? I mean, if this behavior is indeed in the official specification, then promises in asynchronous code does not make any sense to me.

+5
source share
1 answer

Your oboe problem is based on the fact that there are Joson races in the stream, so we never know in advance how many promises there are, so we cannot assign responsibility to Promise.all in Promise.all . We can β€œpromise” the oboe to be able to return promises in our methods.

Typically, I would use RxJS to automatically create a stream from an event. The emitter and RxJS method can already return promises and then aggregate it. Nevertheless, since I do not want to use a library of third-party developers, and it has less educational value, let it implement it:

 function addMap(oboe) { oboe.map = function(selector, mapper){ var promises = []; return new Promise(function(resolve, reject){ // create a new promise oboe.node(selector, function(match){ var result = mapper(match); // get result // signal that we're handling the rejection to make sure it not handled. result.catch(function(){}); promises.push(result); }); oboe.fail(reject); oboe.done(function(){ resolve(promises); }); }); }; } 

What would we do:

 var o = oboe("foo"); addMap(o); o.map("items.*", item => downloadItem(item)).then(result => { // handle result here }); 

Your setTimeout question is very contrived. The vast majority of people do not write code that looks like this in practice - in practice, adding an error handler asynchronously is a rather rare case when you are not working with an API that forces you to do this (for example, the Oboe.js example).

Which is really strange: modern browsers behave differently

This is because Firefox uses the GC to detect raw failures and the Chrome timer. This implementation detail - the only guarantee you will receive is that errors will not be logged if they are attached to a microtask (synchronously or then , which runs on the same move).

+2
source

Source: https://habr.com/ru/post/1234118/


All Articles