How to use promise.all() function in JavaScript
Often we find ourselves in a situation where we want to make multiple request to some API, or maybe multiple APIs in a loop perhaps. And instead of waiting for each response before firing our next request, we can fire them simultaneously and then wait for all our promises to resolve before moving on with our code. This is all possible, thanks to Promise.all().
Example
For this guide, I will take inspiration from our implementation we did for our stock API that we provide for free to anyone. Basically, we have an endpoint that allows anyone to provide it with stock tickers that we will then collect information about from Yahoo Finance API and return to the client.
Example endpoint.
"https://stocks.algobook.info/api/v1/stocks?tickers=AAPL,MSFT,GOOG";
In this case, we want information about three stocks, and the API will do its best to achieve this as fast as possible. One technique used, is Promise.all(). Let's check how we do it.
Implementation
In below example, we will hardcode our tickers and call the Yahoo endpoint in a loop and provide it with our ticker name. We will push the promise in an array, which we will then resolve with Promise.all() and at the end log the final result for our first response in the array, in this case, our AAPL stock.
const axios = require("axios"); (async () => { const promises = []; ["AAPL", "MSFT", "GOOG"].forEach((ticker) => { promises.push( axios.get( `https://query1.finance.yahoo.com/v8/finance/chart/${ticker}?&interval=1d&range=1d` ) ); }); const response = await Promise.all(promises); console.log(response[0]?.data?.chart?.result); })();
console.log() gives us...
[ { "meta": { "currency": "USD", "symbol": "AAPL", "exchangeName": "NMS", "instrumentType": "EQUITY", "firstTradeDate": 345479400, "regularMarketTime": 1682020804, "gmtoffset": -14400, "timezone": "EDT", "exchangeTimezoneName": "America/New_York", "regularMarketPrice": 166.65, "chartPreviousClose": 167.63, "priceHint": 2, ...rest } } ]
And to get the other responses we can just check response[1]
and so on.
Multiple services
We can do calls to multiple services as well in the same loop. In this example, we will both call Yahoo and the stocks.algobook endpoint.
const axios = require("axios"); (async () => { const promises = []; ["AAPL", "MSFT", "GOOG"].forEach((ticker) => { promises.push( axios.get( `https://query1.finance.yahoo.com/v8/finance/chart/${ticker}?&interval=1d&range=1d` ) ); promises.push( axios.get(`https://stocks.algobook.info/api/v1/stocks?tickers=${ticker}`) ); }); const response = await Promise.all(promises); console.log(response[5]?.data); })();
And our console.log() gives us...
[ { "ticker": "GOOG", "open": 104.65, "lastClose": 105.02, "lastPrice": 105.9, "percentage": 0.84, "currency": "USD" } ]
Which is our last reponse in the array, GOOG stock information from the stock API we provide.
Compare the request times
Let's do some time measuring and see if we see some differences in terms of the time that'll take for the request to go through. I will run each implementation three times and take the average number.
Promise.all()
const axios = require("axios"); (async () => { const promises = []; const start = new Date(); ["AAPL", "MSFT", "GOOG"].forEach((ticker) => { promises.push( axios.get( `https://query1.finance.yahoo.com/v8/finance/chart/${ticker}?&interval=1d&range=1d` ) ); promises.push( axios.get(`https://stocks.algobook.info/api/v1/stocks?tickers=${ticker}`) ); }); await Promise.all(promises); const end = new Date(); const result = end.getTime() - start.getTime(); console.log(`Millis: ${result}`); })();
Millis: 411 Millis: 325 Millis: 378 Average: 371,3
Await for each request
Let's change our loop a little bit. Now we will make it wait for each request in the loop, and after the loop is done, we will print the time it took.
const axios = require("axios"); (async () => { const start = new Date(); const tickers = ["AAPL", "MSFT", "GOOG"]; for (let i = 0; i < tickers.length; i++) { const ticker = tickers[i]; await axios.get( `https://query1.finance.yahoo.com/v8/finance/chart/${ticker}?&interval=1d&range=1d` ); await axios.get( `https://stocks.algobook.info/api/v1/stocks?tickers=${ticker}` ); } const end = new Date(); const result = end.getTime() - start.getTime(); console.log(`Millis: ${result}`); })();
Millis: 1675 Millis: 967 Millis: 953 Average: 1198,3
Outro
So, we can conclude that using techniques like Promise.all can be super beneficial for us when it comes to making our code more efficient. In our example, we can make our code 3 (!!) times faster just by applying this simple change. I hope you found this article helpful, and thanks for reading!
Have a great day.