Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suppressing warning about unhandled rejection by the Q library, which seems to be false positive #28

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

wiseman17
Copy link
Contributor

No description provided.

@dpobel
Copy link
Contributor

dpobel commented Nov 12, 2013

For the record I created a bug in JIRA for this: https://jira.ez.no/browse/EZP-21926

(and this needs to be inspected in details before merging)

@jakobwesthoff
Copy link
Contributor

Okay let me try to clarify, what exactly does happen here and whether it can be fixed or not ;)

Q rejection tracking

Idea

The idea behind _Q_s rejection tracking is that if exceptions are thrown during the execution of a promise based application, those might not be captured if failure (rejection) callbacks do not exist. Think of something like this:

function foo() {
    var deferred = Q.defer();
    // async or not is not important here
    deferred.reject(new Error("Blub"));

    return deferred.promise;
}


var promise = foo();
promise.then(
    function() {
        // Do something if successful
    }
);

// Rejection is completely ignored.

In the above code the rejection of the promise is not handled. Therefore it is never discovered, that the promise failed.

Another scenario is that nested promise handlers throw exceptions like in the following example:

function foo() {
    var deferred = Q.defer();

    deferred.resolve();

    return deferred.promise;
}

var promise = foo();
promise.then(
    function() {
        throw new Error("Foo");
    }
).then(
    function() {
        // Never executed
    }
);

In this case a promise handler has thrown an exception. Q catches this Error and delivers it as a promise failure. Even though this failure will bubble up the promise chain it is never caught. The second promise will therefore be not fulfilled, nor will anybody ever again realize that an Error has been thrown.

Therefore the idea in Q is to log non handled rejections (exceptions).

The question that arises is, why are those list of rejections logged to the console even if it is empty?

Realisation

As Q has absolutely no idea when the asynchronous process of handling rejections and stuff has finished it uses a trick to log out the information about rejections.

The developer consoles of the different browsers utilize a lazy rendering technique, to not block the JavaScript execution, while log output is rendered.

Q utilizes this behavior to ensure it always informs the user about unhandled rejections: Internally Q maintains a list of all rejections. Once an arbitrary rejection occurs on any promise it gets added to this list. Once it is handled it is removed from the list again. In order to display this list to the user the first encountered rejection causes Q to issue a console.log statement containing this list. As the contents of this list is automatically referencing the maintained internal rejection list it will always contain the correct information about unhandled rejections. Unfortunately once a log call is issued it can not be removed again. Therefore a logged output containing an empty array means, that all rejections have been properly handled.

To get a feeling for this lazy referencing try executing the following javascript code and watch the developer console :)

setTimeout(function() {
    var myData = []; 
    console.dir(myData);

    myData.push(1);
    myData.push("two");
    myData.push("three");
    myData.push(4);
}, 1);
Silencing the output

Due to this behavior, the only solution to not having the corresponding output inside the developer console is a call to Q.stopUnhandledRejectionTracking().

As it might be interesting during development to ensure the outputted array is empty I would by default disable the rejection tracking, but add an option to the PromiseCAPI which always to keep it enabled during development.

Even though this isn't the nicest solution, I think it is acceptable.

Conclusion

I hope my explanations make sense and are helping to clear things up a little. Essentially it can be said if the logged array is empty everything is good ;).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants