Node await is synchronous

Starting from node 8, or node 6 with babel, we can use a feature named async await. It makes programming asynchronous code in synchronous way. For example, let’s say a function getNumberis returning Promise with resolve, we can call the function using await like this:

async function processNumber(){
  var number = await getNumber();
  number = number + 2;
  return number;
}

Async function will always return Promise, even though it isn’t described in code. Pretty neat huh, now that we can treat the promise as function that return something (synchronously). However, as I had previously assumed, await statement is executed synchronously.

I am using the test scripts at the following github repository. The code in app.js is using Promise.all, while the code in app2.js is using async await. In both code, they will execute same function, called execThings.

var execThings = function(i){
	return new Promise(function(resolve){
		var curIndex = i;
		setTimeout(function(){
			console.log(curIndex, model);
    		resolve(model.num++);
		}, 120 - ((i * i) - (2 * i) + 5));
    });
};

This function is accepting a numeric parameter, then it will resolve an incrementing number, defined in model.num. For the sake of some randomness and asynchronous process, I use setTimeout with randomized timeout based on input argument. When executed, here is one of the result:

12 { num: 0 }
13 { num: 1 }
14 { num: 2 }
15 { num: 3 }
16 { num: 4 }
17 { num: 5 }
18 { num: 6 }
19 { num: 7 }
11 { num: 8 }
10 { num: 9 }
9 { num: 10 }
8 { num: 11 }
7 { num: 12 }
6 { num: 13 }
0 { num: 14 }
5 { num: 15 }
1 { num: 16 }
4 { num: 17 }
3 { num: 18 }
2 { num: 19 }
[ 14, 16, 19, 18, 17, 15, 13, 12, 11, 10, 9, 8, 0, 1, 2, 3, 4, 5, 6, 7 ]

The top list is the log for each promise when executed. The bottom array is the Promise.all result. As we can see here, that Promise.all is executing all functions simultaneously, because the log is in unordered index. But the result is sorted according to executed promise. In the result, index 0, with value 14 is also in index 0 of Promise.all result. Index 1, same with result index, valued 16, and so on.

Now when executing app2.js (I’m using babel due to still using node 6), the result is:

0 { num: 0 }
1 { num: 1 }
2 { num: 2 }
3 { num: 3 }
4 { num: 4 }
5 { num: 5 }
6 { num: 6 }
7 { num: 7 }
8 { num: 8 }
9 { num: 9 }
10 { num: 10 }
11 { num: 11 }
12 { num: 12 }
13 { num: 13 }
14 { num: 14 }
15 { num: 15 }
16 { num: 16 }
17 { num: 17 }
18 { num: 18 }
19 { num: 19 }
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 ]

As we can see here, async await is executed in synchronous process. The index is sorted neatly and the result is also as expected. And when executing the app2.js, it takes around 5 seconds, due to waiting for timeout delay. Meanwhile app.js is executed in up to 1 second.

Conclusion

Despite being very convenient, be aware that async await feature in node 8 or above (or babel) is being executed synchronously. Meanwhile the more complex Promise.all is execute the same process asynchronously. If you have a long-running process that need to be executed in parallel, Promise.all is the answer. However if you certain that the process is still very fast when executed synchronously, it’s okay to use async await since it’s more readable.

Again, you can get the complete test scripts in this  github repository.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s