Is an improvement. And certainly this:
is probably as good as it can get.
Promises are still useful and let’s not forget that async/await does make use of promises under the hood. Did you know that you can attach a then call at the end of an async function you will be able to run a callback after the async function terminates? Also, did you know that if you omit the ‘await’ keyword you get back a promise? So yeah, promises are here to stay and there’s one particular use case where promises can still shine.
Suppose you have a few arbitrary sensors returning some temperatures, min, max, average, that short of thing. Let’s simulate the asynchronous nature of a system like that by using setTimeout:
So, now you have 3 functions taking a few seconds to return the sensor data. The first one takes 2000ms, the second one takes 1000ms and the third one takes 3000ms.
What if we needed to have a function that takes all sensor data and performs a computation based on a formula. We would have to wait for all 3 sensors to finish. Since all 3 functions use promises and we already know the connection between promises and async/await let’s do this using the latest ES7 feature:
Using the performance interface I measured the execution time of the above function to ~6000ms (6006ms to be precise). I don’t know about you but that seems like a lot of time to me and it definitely does not feel like it’s asynchronous at all. Sure we can do better.
The following code makes use of the invaluable Promise.all function:
Promise.all takes an array of promises and returns a single promise that gets resolved when all other promises get resolved. If we use the performance.now() method one more time we can see that the execution time goes down to 3001ms. To compare the two functions you can use this fiddle (only run the fiddle in browsers that do support async/await):
If we change the third timeout’s delay from 3000ms to 4000ms and run the example the above code we see that it takes ~7000ms with async/await and ~4000ms with Promise.all, both reasonable values considering that we increased the delay by 1000ms.
It’s pretty evident that Promise.all is a better method for waiting for multiple promises to resolve but why? Well the reason stands in the order in which the async/await function calls the 3 sensor functions.
This is how the functions get called:
The getSensorAData function is called at the beginning and the getSensorBData function is not called until after getSensorAData has returned. And the same happens with getSensorCData. So we end up with a total time that is the sum of the functions’ execution times plus a few milliseconds because of the call to console.log and CPU time.
The improvement in execution time we achieved by using Promise.all is no small feat. In larger applications the improvement could be massive and until we are able to await multiple async functions at the same time and that feature is supported by the latest version of NodeJS and at least one transpiler, the Promise.all will be the perfect solution and the promise-based syntax will still be alive.
Originally published at www.dimlucas.com on January 16, 2018.