Looping through a list of fetch() calls - javascript

I'm trying to loop through a bunch of data and make asynch calls. However, I'm not getting the syntax right
async function getEmailData(conversationId){
fetch(aysynch)
.then(response => {return response.json(); })
.then(data => {
dictionary = {}
console.log(data)
var info = data.Body.ResponseMessages.Items[0].Conversation.ConversationNodes[0].Items[0]
console.log(info)
var conversationId = info.ConversationId.Id
var from = info.From.Mailbox.EmailAddress
var to = info.ToRecipients.map(function(recipient) {return recipient.EmailAddress})
var date = info.DateTimeReceived
dictionary[conversationId] = {'from':from, 'to': to, 'date': date}
return dictionary
})
}
x = [listOfIds] //10 in total
for (i=0; i<x.length; i++) {
console.log(x[i].ConversationId.Id)
let response = await getEmailData(x[i].ConversationId.Id)
let data = await response
console.log(data)
}
This is printing out all of the ID's and then grabbing the list id in x and running that one 10 times. How do I make the aysnch request for each request?

Some issues:
The function getEmailData is not returning anything. You need to return the result of the promise chain.
async has no use if you don't use await inside such a function
await outside an async function is invalid.
await response is not useful when response is already the result of an await
declare your variables (with let, var, const)
So do this:
function getEmailData(conversationId){
return fetch(aysynch)
.then(response => response.json())
.then(data => {
const dictionary = {};
console.log(data);
var info = data.Body.ResponseMessages.Items[0].Conversation.ConversationNodes[0].Items[0];
console.log(info);
var conversationId = info.ConversationId.Id;
var from = info.From.Mailbox.EmailAddress;
var to = info.ToRecipients.map(recipient => recipient.EmailAddress);
var date = info.DateTimeReceived;
dictionary[conversationId] = {from, to, date};
return dictionary;
});
}
(async function() {
let x = [1, 2, 4, 6, 9, 13, 23, 22, 24, 19]; //10 in total
for (let i=0; i<x.length; i++) {
console.log(x[i].ConversationId.Id);
let data = await getEmailData(x[i].ConversationId.Id);
console.log(data);
}
})(); // Immediately invoked

You should use let. You are are declaring a global variable i.
for (let i = 0; i < x.length; i++) {
console.log(x[i].ConversationId.Id)
let response = await getEmailData(x[i].ConversationId.Id)
let data = await response
console.log(data)
}

Related

iterating Javascript array and delete based on condition

I want to iterate through an array of words, look up the definition and delete the word if no definition is found.
my code looks as follows;
var words = ["word1", "word2", "word3",]
function Meaning(words){
const getMeaning = async () => {
const response = await fetch(`https://api.dictionaryapi.dev/api/v2/entries/en/${words}`)
const myJson = await response.json()
for(i = 0; i < words.length; ++i) {
if(!response[i]){
myJson.splice(i,1)
console.log(myJson)
}
}}
This is not really doing anything atm. Where am I going wrong?
edit to add context
tried like this as well;
for(i = 0; i < words.length; ++i)
fetch(`https://api.dictionaryapi.dev/api/v2/entries/en/${words[i]}`).then((response) => {
if (response === 404) {
let response = words
words[i].splice(i,1)
console.log(response)
}
throw new Error('Something went wrong');
})
.then((responseJson) => {
let response = words
response[i].splice(i,1)
})
.catch((error) => {
console.log(error)
});
I can print out the 404 error when it finds no definition, but I can't remove it from the words array
After quick look at the API, and it appears to handle only single words, so the caller needs to make the requests one at a time. Here's how to do it...
const baseUrl = 'https://api.dictionaryapi.dev/api/v2/entries/en/';
// one word lookup. resolve to an array of definitions
async function lookupWord(word) {
const res = await fetch(baseUrl + word);
return res.json();
}
// resolve to a bool, true if the word is in the corpus
async function spellCheck(word) {
const defArray = await lookupWord(word);
return Array.isArray(defArray) && defArray.length > 0;
}
// create a spellCheck promise for every word and resolve with the results
// note, this mutates the array and resolves to undefined
async function spellCheckWords(array) {
const checks = await Promise.all(array.map(spellCheck));
for (let i=array.length-1; i>=0; i--) {
if (!checks[i]) array.splice(i,1);
}
}
// test it (a little)
let array = ['hello', 'whereforeartthou', 'coffee'];
spellCheckWords(array).then(() => {
console.log(array)
})
try this code, you need to check every single element of array from response
var words = ["word1", "word2", "word3"];
function Meaning(words) {
const getMeaning = async () => {
const response = await fetch(`https://api.dictionaryapi.dev/api/v2/entries/en/${words}`)
const myJson = await response.json()
let result = [];
myJson.forEach(element => {
if(words.includes(element)) {
result.push(element)
}
});
return result;
}
return getMeaning();
}

How to write array data to json?

How to write the data that the loop passes to the array "eventsPolygon", to json. This array returns 4 args. With this method, I get the error "TypeError [ERR_INVALID_CALLBACK]: Callback must be a function. Received undefined"
async function main() {
console.log("Start checking rewards")
const currentBlockNumberPolygon = await maticProvider.getBlockNumber() - 1
const currentBlockNumberBsc = await bscProvider.getBlockNumber() - 1
const oldestBlockNumberPolygon = 22939848
const oldestBlockNumberBsc = 13763979
const eventFilterPolygon = Missions.filters.RewardToPay()
const eventFilterBsc = Rewards.filters.RewardPayed()
let eventsPolygon = []
let eventsBsc = []
for (let i = oldestBlockNumberPolygon; i < currentBlockNumberPolygon - 10000; i += 10000) {
const eventsLoop = await Missions.queryFilter(eventFilterPolygon, i, i + 10000)
eventsPolygon = eventsPolygon.concat(eventsLoop)
const jsonData = JSON.stringify(eventsPolygon);
fs.writeFile('eventsBsc.json', jsonData.finished)
console.log(i)
}
//for(let i = oldestBlockNumberBsc; i < currentBlockNumberBsc-10000; i+=10000) {
//const eventsLoop = await Rewards.queryFilter(eventFilterBsc, i, i+10000)
// eventsBsc = eventsBsc.concat(eventsLoop)
//console.log(i)
//}
console.log('a')
}
JSON.stringify returns a string representation of your JSON. So you cannot do this:
fs.writeFile('eventsBsc.json', jsonData.finished)
Simply write jsonData to the file:
await fs.writeFile('eventsBsc.json', jsonData);
Be aware that this function is async. You need to await it

Recursive function to ensure the return length is 5

I'm fetching some data from an xml source, but I need to check that the length of the array (return value) is 5, sometimes the response serves data with less than 5 elements (it's random).
If the return value (colorArray) is 5, the promise resolves with the correct array. Otherwise, if the function re-runs the promise resolves with undefined.
Appreciate any help in understanding why I'm getting undefined when colorArray.length is less than 5, or if anyone has any better suggestions about how I should run the code.
Thanks.
const runAxios = async () => {
console.log("function");
const res = await axios.get("/api/palettes/random");
let parser = new DOMParser();
let xml = parser.parseFromString(res.data, "application/xml");
let colors = xml.getElementsByTagName("hex");
const colorArray = [];
for (let i = 0; i < colors.length; i++) {
let colorList = colors[i].firstChild.nodeValue;
colorArray.push(colorList);
}
if (colorArray.length === 5) return colorArray;
else runAxios();
};
const result = runAxios();
result.then(e => {
console.log(e);
});
The problem is that you never returned runAxios:
const runAxios = async () => {
console.log("function");
const res = await axios.get("/api/palettes/random");
let parser = new DOMParser();
let xml = parser.parseFromString(res.data, "application/xml");
let colors = xml.getElementsByTagName("hex");
const colorArray = [];
for (let i = 0; i < colors.length; i++) {
let colorList = colors[i].firstChild.nodeValue;
colorArray.push(colorList);
}
if (colorArray.length === 5) return colorArray;
else return runAxios(); // <----------------------------------This
};
const result = runAxios();
result.then(e => {
console.log(e);
});
Also, depending on your requirements, I would suggest a do-while loop:
const runAxios = async () => {
do {
console.log("function");
const res = await axios.get("/api/palettes/random");
let parser = new DOMParser();
let xml = parser.parseFromString(res.data, "application/xml");
let colors = xml.getElementsByTagName("hex");
const colorArray = [];
for (let i = 0; i < colors.length; i++) {
let colorList = colors[i].firstChild.nodeValue;
colorArray.push(colorList);
}
} while(colorArray.length != 5);
return colorArray;
};
const result = runAxios();
result.then(e => {
console.log(e);
});

Axios.get().then() in a for loop

How would I go about running Axios in a for loop, each with a corresponding .then() function. Then after the for loop ends, run another function.
Example:
const array = ['asdf', 'foo', 'bar'];
let users = [];
for (i = 0; i < array.length; i++) {
axios.get('/user/' + array[i].id).then(response => {
// do something with response
users.push(response);
});
}
console.log(users);
const array = [{ id: 'asdf'}, { id: 'foo' }, { id: 'bar' }]; // changed the input array a bit so that the `array[i].id` would actually work - obviously the asker's true array is more than some contrived strings
let users = [];
let promises = [];
for (i = 0; i < array.length; i++) {
promises.push(
axios.get('/user/' + array[i].id).then(response => {
// do something with response
users.push(response);
})
)
}
Promise.all(promises).then(() => console.log(users));
The .then() method of a Promise itself returns a Promise; so you can collect those and await all of them with Promise.all().
Note that even if you're doing this within an async function, you don't want to await inside the for-loop, because then each request will wait for the previous one to finish before it even starts, and presumably you want to run these requests in parallel.
Depending on your use case, a concise async / await function might look like this:
async function getMultiple(...objectsToGet) {
let users = [];
await Promise.all(objectsToGet.map(obj =>
axios.get('/user/' + obj.id).then(response => {
// do something with response
users.push(response);
})
));
return users;
}
// some other async context
console.log(await getMultiple({ id: 'asdf'}, { id: 'foo' }, { id: 'bar' }));
If you are using a more recent version of javascript with async/await support, you can do the following:
const array = ['asdf', 'foo', 'bar'];
let users = [];
for (const id in array) {
const response = await axios('/user/' + id);
users.push(response);
}
console.log(users);
You should collect all the promises inside an array and use promise.all in the following manner -
const array = ['asdf', 'foo', 'bar'];
let promises = [];
for (i = 0; i < array.length; i++) {
promises.push(axios.get('/user/' + array[i].id))
}
Promise.all(promises)
.then(responses => console.log(responses));

Dynamic request with node-fetch

I need to obtain a value from an API which is actualized quickly. The problem is that the code I wrote bring me always the same value. I tried two ways:
var fetch = require("node-fetch");
for(let i=0; i<5; i++){
setTimeout(function(){}, 3000);
fetch('https://api.binance.com/api/v3/avgPrice?symbol=ETHBTC')
.then(res => res.json())
.then(data => {console.log(data.price)});
}
and in a synchronous fashion:
var fetch = require("node-fetch");
var request = async () => {
var response = await fetch('https://api.binance.com/api/v3/avgPrice?
symbol=ETHBTC');
var json = await response.json();
console.log(json.price);
}
for(let i=0; i<5; i++) {
setTimeout(function(){request();}, 3000);
}
but I always obtain something like this:
0.03244206
0.03244206
0.03244206
0.03244206
0.03244206
Any suggestion?
You need to understand that setTimeout doesnt stop the execution of the loop... The loop sets all timeouts to be executed right one after another
const fetch = require("node-fetch");
let i = 0, times = 5;
const interval = setInterval(() => {
if (++i < times) clearInterval(interval);
fetch('https://api.binance.com/api/v3/avgPricesymbol=ETHBTC')
.then(res => res.json())
.then(data => {console.log(data.price)});
},3000);
Using async/await:
const fetch = require("node-fetch");
let i = 0, times = 5;
const interval = setInterval(async () => {
if (++i < times) clearInterval(interval);
const response = await fetch("https://api.binance.com/api/v3/avgPricesymbol=ETHBTC");
const json = await response.json();
console.log(json);
},3000);

Categories

Resources