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

async & performance/ch3 - Promise: a confusing part - reject vs throw not covered #961

Closed
tomwang1013 opened this issue Feb 15, 2017 · 5 comments

Comments

@tomwang1013
Copy link

I've red this chapter, tried some example and found that sometime throw can be used instead of reject, for example, the following 2 promises has the same result:

var p1 = new Promise(function(resolve, reject) { reject('aaaa'); })
var p2 = new Promise(function(resolve, reject) { throw ('aaaa'); })

Both can be catched and output the same error:

p.catch(function(err) { console.log(err); }) // aaaa

But other times throw and reject behavior terribly different:

// use reject
function timeoutPromiseReject(delay) {
    return new Promise( function(resolve,reject){
        setTimeout( function(){
            reject ( "Timeout!" );
        }, delay );
    } );
}

var re = timeoutPromiseReject(2000).catch((err) => { console.log("throw " + err); })
// output "throw Timeout!" and re is rejected

// use throw
function timeoutPromiseThrow(delay) {
    return new Promise( function(resolve,reject){
        setTimeout( function(){
            throw ( "Timeout!" );
        }, delay );
    } );
}

var th = timeoutPromiseThrow(2000).catch((err) => { console.log("throw " + err); }) 
// output "Timeout!" and th is still pending!!

I can't find the answer in this chapter. So am i missing something or we should cover this confusing part?
I googled it and not found something clearly explain this point.

@memoryza
Copy link

i test the example, find th is still resolve , but the "throw" will be throw to global(tips: Uncaught (in promise) test)

@tomwang1013
Copy link
Author

@memoryza i tested in node v6.9.1:

> function timeoutPromise(delay) {
...     return new Promise( function(resolve,reject){
.....         setTimeout( function(){
.......             throw ( "Timeout!" );
.......         }, delay );
.....     } );
... }
undefined
> var th = timeoutPromise(2000).catch((err) => { console.log("throw " + err); })
undefined
> Timeout!
> th
Promise { <pending> }

I seemed that th is was pending forever, hanged on. And the err throwed was NOT promise-catched

@getify
Copy link
Owner

getify commented Feb 15, 2017

throw (and the corresponding try..catch that's inside the Promise machinery to catch its exception) is purely synchronous and thus doesn't work across async boundaries. When you throw inside a setTimeout(..) callback, the surrounding promise context is on a different tick of the event loop and will therefore not catch the exception... instead that exception is handled in the global context as an "uncaught exception".

This is pretty much the main reason for needing the reject(..) function, which is a lexical identifier and thus via closure is preserved across those async boundaries. When you call reject(..) it will reject the promise, even though we're on a different tick of the event loop.

@tomwang1013
Copy link
Author

tomwang1013 commented Feb 15, 2017

@getify thanks for reply. I understand your meaning. But could you please explain the first example: sometimes they behavior the same? Could we conclude that they are the same in synchronous env, and different in async env, when used in promise context?
And any suggestion on when to use which?

@getify
Copy link
Owner

getify commented Feb 15, 2017

I would always use reject(..) as it will always work, where throw will only sometimes work.

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

No branches or pull requests

3 participants