How to write array data to json? - javascript

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

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();
}

Trying to use replace() method on files by passing the string not working - JS

I'm trying to replace a string, but when i try to do it on a file, it does not work. Or only the last file will work.
Main Code (inside a class method):
const funcs = fs.readdirSync(path.join(__dirname, "../funcs")).filter(file => file.endsWith('.js'));
this.functions = this.code.split("$");
const functions = this.functions
for (const func of funcs) {
for (let x = functions.length - 1; x > 0; x--) {
let i = 0;
const res = await require(`../funcs/${func}`)(client, this.code.toString(), this._author);
console.log(x);
console.log(res);
console.log(functions);
return res;
i++;
}
}
ping.js:
const ping = (client, code, author) => {
const result = code.split("$[ping]").join(client.ws.ping)
return result;
}
module.exports = ping;
messageAuthorTag.js:
const Util = require('../utils/util');
const messageAuthorTag = (client, code, author) => {
if (code === null) return;
const res = code.split("$[message.author.tag]").join(`${author.tag}`);
return res;
}
module.exports = messageAuthorTag;
Using it : "ping: $[ping] author tag: $[message.author.tag]"
Output:
ping: $[ping] author tag: Example#0001
Your issue is that you return res in the middle of a for loop. This means it won't do anything else in the function and will skip the rest of the loops (like running the other functions!)
As an additional note, you could also remove the let i = 0 and i++ since that doesn't seem to be used for anything.

Issues with Array Variable

app.get("/indsalesx/:store/:mm", (req, res) => {
connect();
let ddd = [];
let staffarray = [{}];
let store = req.params.store;
let mm = req.params.mm;
const SP = mongoose.model(`sales${store}`, Sales);
let num = stafflist[store].length - 1;
for (i = 0; i <= num; i++) {
let staffname = stafflist[store][i];
let calc = 0;
SP.find(
{ v_salesperson: stafflist[store][i], v_month: mm },
"v_amount",
(err, doc) => {
let t = doc.length - 1;
doc.map((res) => {
calc = calc + res.v_amount;
});
ddd.name = staffname;
ddd.amount = calc;
staffarray.push(ddd);
}
);
}
console.log(staffarray);
});
The issue I have is: Why is staffarray returning an empty array? staffarray was declared as an empty array of objects, and in a loop function, objects were pushed to to array. But when I console.log(staffarray), it returns the empty array of objects declared initially.
Any help on what to do?
When using find(), you can use 2 approaches.
Pass a callback function
await the function to execute and return the results.
It appears that you used the first approach which means that you are passing a callback into the find() method which handles the result once received.
The console.log() code line will execute before the result will return since it's the next line to execute after the for loop.
So, let's go through what it happening here:
Javascript is executing the find() code line.
That line of code is being placed in the web API which are the pieces of the browser in which concurrency kicks in and makes the call to the server for us.
The console.log() line is being executed with an empty array (since the results haven't been received yet.
After some time, results came back and the callback is being set in the callback queue.
The JS event loop takes the callback from the callback queue and executes it.
This is part of the javascript event loop. you could read more about this here
Mongoose documentation: Model.find()
you can use for of with async/await instead of for
app.get("/indsalesx/:store/:mm", async(req, res) => {
connect();
let ddd = [];
let staffarray = [{}];
let store = req.params.store;
let mm = req.params.mm;
const SP = mongoose.model(`sales${store}`, Sales);
let num = stafflist[store].length - 1;
var list = Array.from(Array(num).keys());
for (let i of list) {
let staffname = stafflist[store][i];
let calc = 0;
let doc = await SP.find(
{ v_salesperson: stafflist[store][i], v_month: mm },
"v_amount"
);
let t = doc.length - 1;
doc.map((res) => {
calc = calc + res.v_amount;
});
ddd.name = staffname;
ddd.amount = calc;
staffarray.push(ddd);
}
console.log(staffarray);
});
I have been able to solve it, all I needed was proper structuring with the async and await statements.
app.get("/indsalesx/:store/:mm", async (req, res) => {
connect();
let ddd = {};
let staffarray = [];
let store = req.params.store;
let mm = req.params.mm;
const SP = mongoose.model(`sales${store}`, Sales);
let num = stafflist[store].length - 1;
for (i = 0; i <= num; i++) {
let staffname = stafflist[store][i];
let calc = 0;
await SP.find(
{ v_salesperson: stafflist[store][i], v_month: mm },
"v_amount",
(err, doc) => {
let t = doc.length - 1;
doc.map((res) => {
calc = calc + res.v_amount;
});
staffarray.push({ name: staffname, amount: calc });
}
);
}
console.log(staffarray);
res.send({ data: staffarray });
});

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);
});

Looping through a list of fetch() calls

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)
}

Categories

Resources