I expected an array of messages that depend on the response codes of the services but i'm actually getting TypeError: result.push is not a function from code below:
import axios from "axios";
const services = ["https://google.com", "https://facebook.com", "https://youtube.com"];
const results = await services.reduce(async (result, service) => {
const response = await axios.get(service);
result.push(response.status === 200 ? `${service} is up.` : `${service} seems down.`);
return result;
}, []);
console.log(results);
I tried setting initial reduce() value to Promise.resolve([]) but it doesn't make any changes.
However when i removed async & await stuff error no longer shows up but status checks work wrong now.
import axios from "axios";
const services = ["https://google.com", "https://facebook.com", "https://youtube.com"];
const results = services.reduce((result, service) => {
const response = axios.get(service);
result.push(response.status === 200 ? `${service} is up.` : `${service} seems down.`);
return result;
}, []);
console.log(results);
DO NOT use functions that return promises in the .reduce() method!
Why are you even using the .reduce() method when what you want returned is an array of the same length? Use .map() instead.
Also, use try...catch in case any errors occur and handle them appropriately. If a request totally fails, the entire program will crash with your current code.
There are multiple ways you can do this. The first way is to fetch all of the data first, then map through it:
import axios from 'axios';
const services = ['https://google.com', 'https://facebook.com', 'https://youtube.com'];
// Create an array of promises which will fetch the services
// We do this PRIOR to manipulating the data
const promises = services.map((service) =>
(async () => {
try {
const res = await axios.get(service);
return {
status: res.status,
service,
};
} catch (error) {
return {
status: null,
service,
};
}
})()
);
// Wait for all of them to finish
const serviceData = await Promise.all(promises);
const results = serviceData.map(({ status, service }) => (status && status === 200 ? `${service} is up` : `${service} is down`));
console.log(results);
Or, you can do it all in one single loop:
import axios from 'axios';
const services = ['https://google.com', 'https://facebook.com', 'https://youtube.com'];
const results = [];
for (const service of services) {
try {
const res = await axios.get(service);
results.push(`${service} is ${res?.status === 200 ? 'up' : 'down'}`);
} catch (error) {
results.push(`${service} is down`);
}
}
console.log(results);
You can also use for await in combination with the first solution if you're feeling fancy and like optimization.
import axios from 'axios';
const services = ['https://google.com', 'https://facebook.com', 'https://youtube.com'];
const results = [];
const promises = services.map((service) =>
(async () => {
try {
const res = await axios.get(service);
return {
status: res.status,
service,
};
} catch (error) {
return {
status: null,
service,
};
}
})()
);
for await (const { status, service } of promises) {
results.push(`${service} is ${status === 200 ? 'up' : 'down'}`);
}
console.log(results);
The running time of all these solutions is: