How to retrieve value from promise [duplicate] - javascript

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

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

array return value is always empty

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

execute axios request multiple times only get one output

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.

How to write callback function inside for loop in node.js

I am trying to write a function inside a for loop. But the loop is not waiting until getting response for the function inside. How can I stop the loop until getting response for the function every time?
In this process the next loop is dependent on the response of the function.
My example code:
var a = function(data, callback) {
var d = 1;
for (var i = 0; i < data.length; i++) {
b(d, function(err, result) {
if (!err) {
d = result;
}
if ((i + 1) === data.length) {
callback(err, 'something');
}
});
}
}
var b = function(data, callback) {
var c = data + 1;
callback(null, c);
}
In this code the for loop is not waiting until it gets the response form the function b.
You can easily iterate your input array by calling a recursive function call within your callbacks:
'use strict';
const a = function(data, callback) {
let i = 0;
let sum = 0;
// loop function
function next() {
const x = data[i++];
if (!x) {
return callback(null, sum);
}
return b(x, (err, data) => {
sum += data;
next();
});
}
next(); // starts iterating
}
// multiplies data * 3
const b = function(data, callback) {
let c = data * 3;
callback(null, c);
}
a([1, 2, 3], (err, data) => {
console.log(data); // prints 18
});
Use Promises
Your code can easily be refactored to use Promises:
function a (data) {
let promise = Promise.resolve(1);
for (let i = 0; i < data.length; i++) {
promise = promise.then(b);
}
return promise.then(function (v) {
// v is the value computed by the promise chain
return 'something';
});
}
function b (data) {
// some async action that returns a promise
return Promise.resolve(data + 1);
}
Usage:
a(['a', 'b', 'c']).then(result => console.log(result)); // logs 'something'
Use async functions
Working with promises allows you to treat asynchronous code like synchronous code using async functions:
async function a (data) {
let v = 1;
for (let i = 0; i < data.length; i++) {
// looks like synchronous code, but is asynchronous
v = await b(v);
}
// v is the value computed by the asynchronous loop
return 'something';
}

How to wait for the complete execution of a loop Node.js

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

Categories

Resources