i have the following code:
for (var i = 0; i < subscriptions.length; i++) {
axios.get(`SOME_URL/${subscriptions[i]}`, config1)
.then((result) => {
return result.data.subscriptionId
})
.then((result) => {
axios.get(`SOME_URL/${result}/devices`, config2)
.then((data) => {
activationCodeAndDevice[data.data.devices[0].id] = result
return activationCodeAndDevice
})
.then((result) => {
console.log(result);
})
.catch((err) => {
console.log(err);
})
})
.catch((err) => {
console.log(err);
})
}
Now the console.log(result) will print as many times as the for loop goes through. What is your suggestion to only print the result one time when all the Axios requests are done executing?
Now i did build something like this but with 3 different requests:
var request1 = axios.get('request1')
var request2 = axios.get('request2')
var request3 = axios.get('request3')
Promise.allSettled([request1, request2, request3])
.then((values) => {
//do something
})
.catch((err) => {
//do something
})
I have no idea on how to get for a request that I have to perform multiple times, depending on an array of values, but only get one time the output. Of course, i could write it in a file and just have a look at the file once the data is written, but i want it to have it on the console.
thanks
Do something like:
const promises = subscriptions.map(subscription => axios.get(`SOME_URL/${subscription}`, config1))
Promise.allSettled(promises).then((values) => {
...
})
The map converts the requests to an array of promises, and the Promise.allSettled waits for the array to succeed.
If you really insist in using a for loop you can also do the following:
let promises = [];
for(let i = 0; i < subscriptions.length; i++) {
promises.push(axios.get(`SOME_URL/${subscription}`, config1));
}
Promise.allSettled(promises).then((values) => {
...
})
I managed to solve it like this:
const getSubscriptionResponse = subscriptions.map(subscription => axios.get(`SOME_URL/${subscription}`, config1))
Promise.allSettled(getSubscriptionResponse).then((values) => {
var subscriptionsValue = []
for (let i = 0; i < values.length; i++) {
subscriptionsValue.push(values[i].value.data.subscriptionId);
}
const getDeviceResponse = subscriptionsValue.map(sub => axios.get(`SOME_URL/${sub}/devices`, config2))
Promise.allSettled(getDeviceResponse).then((res) => {
var finalResults = {}
for (let j = 0; j < res.length; j++) {
finalResults[res[j].value.data.devices[0].id] = subscriptionsValue[j]
}
console.log(finalResults);
})
})
this will only print once the finalResult
{
A:A,
B:B,
C:C,
.
.
.
}
it looks a bit messy with all the for loops but I actually need to get the data from the array of responses.
Related
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();
}
i'm trying to program a prototype right now, however i have a problem, my return values, my output overall always returns an empty array.
If I put everything into a function it works, but if I divide everything into code blocks it doesn't work anymore.
I always get an empty array back as I said.
What am I doing wrong?
async function dataLength(){
return new Promise((resolve, reject) => {
pdo.query(`SELECT * FROM mainsites`, function(err, result) {
let results = result;
let resultsLength = results.length;
let dataIndexMainId = [];
for(let index = 0; index < resultsLength; index++){
dataIndexMainId[index] = results[index]["id"];
}
resolve();
})
})
}
async function getSubSitesIndex(length){
let dataSitesIndex = [];
for(let i = 0; i <= length; i++){
await new Promise((resolve) => {
pdo.query("SELECT * FROM subsites WHERE main = ?",[i] , function(err, result) {
dataSitesIndex[i] = result;
resolve();
})
})
}
let filterDataSitesIndex = dataSitesIndex.filter(String);
console.log(filterDataSitesIndex);
return filterDataSitesIndex;
}
async function getIndex(paramIndex){
let indexResult = await paramIndex;
let indexArray = [];
for (let indexRes of indexResult){
for(let res of indexRes){
indexArray.push(res);
}
}
return indexArray;
}
if I execute the code like this
getIndex(
await getSubSitesIndex(
await dataLength()
)
);
In dataLength, your pdo.query call is not properly promisified.
However, you shouldn't have to write 3 functions for this at all. Do not make multiple queries to your database. Use a single query that does a JOIN - much more efficient!
function getIndex() {
return new Promise((resolve, reject) => {
pdo.query(`
SELECT mainsites.id AS main_id, subsites.id AS sub_id
FROM mainsites
JOIN subsites ON subsites.main = mainsites.id;
`, [], (err, result) => {
if (err) reject(err);
else resolve(result);
});
});
}
Here I have required the sql in my main index file
seeded the database and checked that the sql query returns
// require sql connection from main index
const connection = require('./index');
async function tow() {
let arr = [];
let one = await connection.query("Select name FROM department", (err, res) => {
if (err) throw err;
// console.log(res);
console.log('1'arr);
for (let i = 0; i < res.length; i++) {
// pushing to the array here
arr.push(res[i].name);
}
console.log('2',arr);
});
console.log('3',arr);
return one;
}
// I want this function to return array with the pushed elements
tow();
You need to return arr. Also you are mixing the promise style with the callback style of async, you can do either one, but not a mix. Try something like this.
If connection.query returns a promise:
async function tow() {
let arr = [];
let one = await connection.query("Select name FROM department").then(res => {
// console.log(res);
console.log('1', arr);
for (let i = 0; i < res.length; i++) {
// pushing to the array here
arr.push(res[i].name);
}
console.log('2',arr);
return arr; // need to return arr
},
err => console.error(err));
console.log('3',arr);
return one;
}
tow().then(res => console.log('result', res));
In your case, where connection.query expects a callback function, you can convert the callback to a promise like this.
function tow() {
return new Promise((resolve, reject) => {
let arr = [];
connection.query("Select name FROM department", (err, res) => {
if (err) reject();
// console.log(res);
console.log('1', arr);
for (let i = 0; i < res.length; i++) {
// pushing to the array here
arr.push(res[i].name);
}
console.log('2',arr);
resolve(arr);
});
})
}
// I want this function to return array with the pushed elements
tow().then(res => console.log('result', res));
Here's a codeSandbox
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
I've been working on a project and I need some help regarding this:
I have a promise inside a function and I need to return the value of "current" so that I can use it elsewhere.
I'm retrieving data from Firebase, then I shuffle the result and extract only 10 elements from the result.
function retriveData() {
//declaration of variables ...
axios.get("Firebase link")
.then((response) => {
keyArray = Object.keys(response.data);
let k = shuffle(keyArray);
//shuffle is a function to shuffle the key results
for (var i = 0; i < 10; ++i) {
current[i] = response.data[k[i]];
}
});
return current;} //I want this variable to end up with the promise result in current
I know, this is not how promises work but I need a solution to solve this problem.
Thanks!
axios.get is asynchronous, so either you pass a callback to retrieveData, or it needs to return a Promise itself. There's no way around that.
Using a callback (no error handling):
function retriveData(callback) {
axios.get("Firebase link")
.then((response) => {
keyArray = Object.keys(response.data);
let k = shuffle(keyArray);
//shuffle is a function to shuffle the key results
for (var i = 0; i < 10; ++i) {
current[i] = response.data[k[i]];
}
callback(null, current);
});
}
retrieveData((err, result) => console.log(result));
Using a Promise (no error handling):
function retriveData() {
return new Promise((resolve) => {
axios.get("Firebase link")
.then((response) => {
keyArray = Object.keys(response.data);
let k = shuffle(keyArray);
//shuffle is a function to shuffle the key results
for (var i = 0; i < 10; ++i) {
current[i] = response.data[k[i]];
}
resolve(current);
});
}
retrieveData().then((result) => console.log(result));
[EDIT] The above example is mean for illustrative purposes. Since axios.get already returns a Promise, it can be returned back directly from retrieveData.
function retriveData() {
return axios.get("Firebase link")
.then((response) => {
keyArray = Object.keys(response.data);
let k = shuffle(keyArray);
//shuffle is a function to shuffle the key results
for (var i = 0; i < 10; ++i) {
current[i] = response.data[k[i]];
}
return current;
});
}
retrieveData().then((result) => console.log(result));
Try this: I am making your retriveData function as a promise so you can use it anywhere in your program
function retriveData() {
//declaration of variables ...
return new Promise((resolve, reject) => {
axios.get("Firebase link")
.then((response) => {
keyArray = Object.keys(response.data);
let k = shuffle(keyArray);
//shuffle is a function to shuffle the key results
for (var i = 0; i < 10; ++i) {
current[i] = response.data[k[i]];
}
// if everything fine, if you get any conditional error then call reject();
resolve(current);
});
})
}
//call the function like promise
retriveData().then(result => {
//current will come here
console.log('result comes here');
}).catch(error => {
//error comes here (reject error)
console.log('error');
})
I have such a loop :
var someArray = [];
for(var i = 0; i < myArray.length; i++) {
var tempArray = [];
arangodb.query('somequery')
.then(
cursor => cursor.all()
).then(
keys => tempArray = keys,
err => console.error('Failed to execute query:', err)
).then(function () {
someArray.push.apply(someArray, tempArray);
});
}
I want to do other operations when all tempArrays are collected in someArray. But since Node.js is async, I don't know how to do it. Can you help me with that? Thanks in advance.
This will result in a flat array of keys from cursor.all()
any arangodb.query that fails will be ignored (still with console output though)
Promise.all(myArray.map(item =>
arangodb.query('somequery')
.then(cursor => cursor.all()))
.catch(err => console.error('Failed to execute query:', err))
)
// remove rejections, which will be undefined
.then(results => results.filter(result => !!result))
// flatten the results
.then(results => [].concat(...results))
.then(results => {
// do things with the array of results
})
you need to use Promise.all()
var someArray = [];
function queryDB(){
return arangodb.query('somequery')
.then(
cursor => cursor.all()).then(
keys => tempArray = keys,
err => console.error('Failed to execute query:', err)
).catch(function(err){
console.log('Failed');
})
}
var promiseArray = [];
for(var i = 0; i < myArray.length; i++)
{
promiseArray.push(queryDB());
}
Promise.all(promiseArray).then(function(results){
someArray = results.filter(result => !!result);
})
basically queryDB() would return a promise, you can do Promise.all() to wait for all promises to resolve and then you can access the result in result
The only way to track if all your async operations are complete or not is to simply keep count of success callback triggers and failure callback triggers. Following should help you out.
let count = 0;
const checkCompletion = (curr, total) => {
if (curr < total) {
// Not all tasks finised
} else {
// All done
}
};
for(var i = 0; i < myArray.length; i++) {
var tempArray = [];
arangodb.query('somequery')
.then(cursor => cursor.all())
.then(keys => {
// success
count += 1;
checkCompletion(count, myArray.length);
}).catch(e => {
// failure
count += 1;
checkCompletion(count, myArray.length);
});
}