Exposed promises don't match promise spec
See original GitHub issueHey, came across minor issues earlier with the promise polyfill earlier (https://github.com/airbrake/airbrake-js/pull/402) but I had thought that the issues were internal to airbrake-js
only; I had not realized these promises were actually exposed to consumers of the library (see client.notify
).
Issue 1: promises from airbrake-js
cannot be correctly chained.
A common usage of promises is to do:
myPromise.then(/* asynchronous stuff happens here*/).then(/* more asynchronous stuff happens here*/)
However, this will not work with the promise exposed from airbrake-js
.
promise.then
:
then(onResolved: OnResolved, onRejected?: OnRejected): Promise {
// only showing relevant lines
this.onResolved.push(onResolved);
return this;
}
promise.resolve
:
for (let fn of this.onResolved) {
fn(value);
}
There’s two bugs with the above code:
- all
.then
s will be resolved as soon as the promise is resolved - all
then
s will be resolved with the same values
This also is the case with .then(onFulfilled, onRejected).catch(onRejected2)
: both onRejected
and onRejected2
are invoked on promise rejection, and they should not be. (See https://github.com/urbanmassage/promise-cb/blob/master/to.ts for usage of this pattern)
Issue 2: (not as important, but while I’m here: incorrect internal usage of promises in client.notify
):
for (let reporter of this.reporters) {
reporter(notice, this.opts, promise);
}
If you have multiple reporters, you’ll be re-triggering the same promise and throwing errors as a result. This should be promise.all
’d.
I know from the previously-reported promise issue that you’re hesitant to bring in a 3rd-party promise polyfill due to size, and I completely understand your concern. When I thought the promises were internal to airbrake-js
this made sense to me. However exposing a ‘promise’ to consumers of your library which is either buggy or doesn’t match specifications is almost certainly going to cause issues for your users. In our case, this caused production container crashes as our error-handling path itself threw errors due to the .then().catch()
bug outlined above. There are multiple (https://github.com/taylorhakes/promise-polyfill, https://github.com/stefanpenner/es6-promise) good very lightweight promise libraries now available, and at <1KB they seem worth another look.
Issue Analytics
- State:
- Created 6 years ago
- Comments:6 (6 by maintainers)
Top GitHub Comments
There is a dependency on
error-stack-parser
in https://github.com/airbrake/airbrake-js/blob/master/src/processor/stacktracejs.ts#L4. It is not copied to the repo, but it is included into compiled and minified notifier. I think the same approach should be applied to promise polyfil.Absolutely, I wasn’t going to be able to get a PR up for a bit. Thanks @vmihailenco