question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Exposed promises don't match promise spec

See original GitHub issue

Hey, 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:

  1. all .thens will be resolved as soon as the promise is resolved
  2. all thens 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:closed
  • Created 6 years ago
  • Comments:6 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
vmihailencocommented, Mar 27, 2018

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.

0reactions
RandomSeededcommented, Mar 30, 2018

Absolutely, I wasn’t going to be able to get a PR up for a bit. Thanks @vmihailenco

Read more comments on GitHub >

github_iconTop Results From Across the Web

Resolve Javascript Promise outside the Promise constructor ...
I'm just learning Promises but have been consistently puzzled by the fact that you don't appear to be able to resolve them "somewhere...
Read more >
Promises | Docs | ractivejs.org
Promises are a way to deal with asynchronous operations - that is, operations that don't complete immediately. Async operations are common in JavaScript,...
Read more >
The Revealing Constructor Pattern - Domenic Denicola
I want to document an interesting pattern we've seen emerge in some recent web platform specs, including promises and streams.
Read more >
Promise - JavaScript - MDN Web Docs
The Promise object represents the eventual completion (or failure) of an asynchronous operation and its resulting value.
Read more >
Promises/A+
This specification details the behavior of the then method, providing an interoperable base which all Promises/A+ conformant promise implementations can be ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found