archives

« Bugzilla Issues Index

#2831 — 25.4 Promises


If an exception is thrown inside of an onFulfilled callback function that was given as Parameter to the then(25.4.5.3) method, without any Additional then(or catch) calls, that exception will be catched by PromiseReactionTask(25.4.2.1), without being rethrown.

This happens because inside of the then(25.4.5.3) method a new promisecapability record is created which includes a new promise, that doesn't get a Default callback handler for onRejected. So when the exception is thrown it goes up to PromiseReactionTask is then delegated to this new PromiseCapability record, and delegated to the reject method, and then to the TriggerPromiseReactions, which should Enqueue a PromiseReactionTask for every PromiseRejectReactions, but These are empty at that Point, so TriggerPromiseReactions just returns undefined, as a NormalCompletion.

I would expect the exception to get rethrown so that it lands inside NextTask (8.4.2) Operation.

I created a working solution by adding a flag to Promise that tells if it was just created.
Also i add a Default promiseRejectReaction to the promise of the new promiseCapability record that is created inside the then method.
Finally i added a check in then beginnig of the then method and if the flag is set i clear the promiseRejectReactions and unset the flag.
This throws the exception as expected.

I tested my solution with:
https://github.com/promises-aplus/promises-tests

If this was actually the intended behavior i would pretty much love to hear why, because i obviously didn't get it. And i just spend alot of time figuring this out.
Because my exceptions weren't showing up as expected.


This is how promises work. It allows code like

```js
var promise = anotherPromise.then(value => {
if (!isValid(value)) {
throw new Error('Invalid value ' + value + '!');
}
});

// later, after some other async processing takes place:
doAsyncStuff().then(() => {
promise.catch(error => showUser(error.message));
});
```

Promises can hold rejections indefinitely, until someone listens to them. Modern promise environments provide debugging experiences that allow you to introspect any currently-rejected promises.


Ok i didn't know that. I expected this to work differently, is there any documentation how it came to this decision?

I thought, since it is async, that the Operation that sets up the promises should also Setup exception handling, before giving control to the async Operation. Which then expects tobe Setup completly, and if it encounters an exception should behave as stated. So that an unhandled exception is really thrown. Thinking of async operations in a more synchronous way.

Also what brought me to my conclusion was the line:
1.If result is an abrupt completion, then perform implementation defined unhandled exception processing.
-- in NextTask (8.4.2)
Which will never be hit with an abrupt completion, at least not from any promise related Task.

Thanks for the quick Response.


(In reply to comment #2)
> Also what brought me to my conclusion was the line:
> 1.If result is an abrupt completion, then perform implementation defined
> unhandled exception processing.
> -- in NextTask (8.4.2)
> Which will never be hit with an abrupt completion, at least not from any
> promise related Task.

It is possible to take that step with promise tasks, for example using this code [1]. But the results are implementation defined, for example V8 simply ignores the exception (cf. the empty catch block in [2]).

[1] https://github.com/anba/es6draft/blob/f2255ae58fed3e8c4f7153c5bea654d2b14fa2df/src/test/scripts/suite/lib/promises.js#L13-L19
[2] https://code.google.com/p/v8/source/browse/branches/bleeding_edge/src/promise.js?spec=svnr21247&r=r21247#179