Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what happens when a Promise never resolves? [duplicate]

Tags:

I have this very confusing snippet of code using es6 async await syntax. What I would expect to happen is that the process hangs on the await line forever, since the resolve function is never called. However, what actually happens is that "start" is outputted and then the process exits with no more output.

const simple = async () => {   console.log('start')   await new Promise(resolve => {})   console.log('done.') } simple() 

this code below however, will print "start", wait 1 second, and the print "done."

const simple = async () => {   console.log('start')   await new Promise(resolve => setTimeout(resolve, 1000))   console.log('done.') } simple() 

My closest guess to what this means (without any evidence) is that while node is waiting on a promise, it keeps track of the active things happening in your code, when there is nothing else happening, it simply exits. Can someone explain why the code exits here?

running node v8.7.0

like image 970
andykais Avatar asked Oct 27 '17 03:10

andykais


People also ask

What happens if promise is never resolved?

Since you don't call resolve() , that code will never execute and thus the console will not print "done". The body of the Promise is, however, executed immediately, and since it's empty, there is nothing left for the program to execute!

What happens when promise all fails?

Promise.all fail-fast behaviorPromise.all is rejected if any of the elements are rejected. For example, if you pass in four promises that resolve after a timeout and one promise that rejects immediately, then Promise.all will reject immediately.

What happens if a promise is resolved twice?

No. It is not safe to resolve/reject promise multiple times. It is basically a bug, that is hard to catch, becasue it can be not always reproducible.

Can you await a promise twice?

The implication of this is that promises can be used to memoize async computations. If you consume a promise whose result will be needed again later: consider holding on to the promise instead of its result! It's fine to await a promise twice, if you're happy to yield twice.


2 Answers

My closest guess … it keeps track of the active things happening in your code, when there is nothing else happening, it simply exits.

This is essentially correct. Node keeps a reference count of things like timers and network requests. When you make a network, or other async request, set a timer, etc. Node adds on to this ref count. When the times/request resolve Node subtracts from the count.

This count is how Node decides whether to exit at the end of the event loop. When you get to the end of the event loop Node looks at this count and if it's zero exits. Simply making a promise, doesn't add to the ref count because it's not an async request.

There's a good talk about some of this by [Node core developer] Bert Belder that's helpful: https://www.youtube.com/watch?v=PNa9OMajw9w

like image 175
Mark Avatar answered Sep 23 '22 22:09

Mark


Right, you have a misunderstanding of what's happening.

Like you say, code will never continue after that await call for the reason you mention, but that doesn't matter.

When you call simple(), that method itself returns a promise - and you're not waiting on that promise. Your execution continues after calling simple() and instantly and hits the end of your program.

To go into more detail, nodejs will exit when there are no more callbacks to process. When you return your broken promise, you have not created a callback in the nodejs queue (like you would if you did a http request for instance). If you do something to keep nodejs alive, you'll see that done never gets executed.

const simple = async () => {   console.log('start')   await new Promise(resolve => {})   console.log('done.') } var promise = simple();  // keep the application alive forever to see what happens function wait () {     setTimeout(wait, 1000); }; wait(); 

If there is a pending callback (created by setTimeout, or from loading a resource, or waiting for an http response) then nodejs will not exit. However, in your first example, you don't create any callbacks - you just return a broken promise. Nodejs doesn't see anything "pending" there, so it exits.

Essentially at the end of your simple call, you have no more code to execute, and nothing pending (no waiting callbacks) so nodejs safely knows there is nothing else to be done.

like image 35
caesay Avatar answered Sep 22 '22 22:09

caesay