let getOeReport = async (req, res) => {
try {
let searchFormatForReason = {
"query": {
"reasonCode": null,
},
"fields": {
'reason': 1, '_id': 0
}
}
let result = await oeDao.getOeReport(searchFormat)
let resultReasons =
result.map(async res =>
res.sequences.map(inter =>
inter.interrupts.map((interrupts) => {
searchFormatForReason.query.reasonCode = interrupts.reason
reasonDao.getReasonByFields(searchFormatForReason)
})
)
)
console.log(resultReasons)
res.status(200).json({
status: "Success",
data: {
result: result
}
});
} catch (err) {
console.log(err)
res.status(400).json({
status: "Failure"
});
}
};
Here in the above code, If I try to console the resultReasons means I'm getting null. Result variable has nested array of objects so that, I need 'reason' value inside interrupts array which is inside sequences array and that is within the result array. And i should make API request with that value and I could push it into resultReasons array. Please someone help me... Thank You
let resultReasons =
result.map(async res =>
res.sequences.map(inter =>
inter.interrupts.map((interrupts) => {
searchFormatForReason.query.reasonCode = interrupts.reason
reasonDao.getReasonByFields(searchFormatForReason)
})
)
)
In this piece of your code you are using async so you must be receiving a Promise, since you are not making use of await within that async function I don't see the reason of keeping it, however you can just add an await as per the code below and should fix the issue (you are already using async on getOeReport so it will work without any modifications)
let resultReasons =
await result.map(async res =>
res.sequences.map(inter =>
inter.interrupts.map((interrupts) => {
searchFormatForReason.query.reasonCode = interrupts.reason
reasonDao.getReasonByFields(searchFormatForReason)
})
)
)
But you are saying you get null which I don't understand how you are getting it, this because again you are using an async function within the first map, hence you must get a Promise, the only way I see your variable can be null is if the result variable is null, BUT it should trigger an Exception so your console.log will never be excecuted
Related
I'm trying to do a search using FindOne inside map but it never finds the data by Product Id. I don't understand the reason. Im using express on nodejs.
This is my code:
const calc = (details) => {
let grandSubtotal = 0;
details.map( async detail => {
const {verifyProduct} = await Product.find({ _id: detail._id});
console.log(detail._id);
console.log(verifyProduct); // UNDEFINED
...
Should be:
const result = await Promise.all(details.map( async (detail) => { … } ));
when you do it like you done you will get a pending promise object that never going to be resolved, I don’t know if you want to return some results, if no just do await Promise.all
Also this should be:
const calc = async (details) => { … }
Mongoose find returns a list of results. findOne returns an object.
The code is doing the equivalent of:
const {verifyProduct} = []
Use findOne to get an object to destructure, and test the result before use.
details.map( async (detail) => {
const res = await Product.findOne({ _id: detail._id });
if (!res) {
//throw new Error('No id '.detail._id)
console.log('No id', detail._id)
}
const { verifyProduct } = res
console.log(detail._id);
console.log(verifyProduct);
}
Also (as #antokhio noted), if you want to use the returned result array of the details.map you will need to await those as well.
You don't need await here
Product.find(({ _id }) => _id === detail._id );
I'm looking to assign a value to an array of objects inside a Axios call. I can't figure out how to assign the values to the new array. Below is the code I have so far.
Thank you.
app.get('/matchedusers', (req, res) => {
plexClient.getAllUsers().then(plexUsers => {
axios.get('https://tautulli.link/api/v2?apikey=API-KEY&cmd=get_users_table&length=150')
.then((tautulliUser) => {
let tautulliUsers = tautulliUser.data.response.data.data
let matchedUsers = []
let timedUsers = []
// Doing a check to see if tautulli user is also a plex user.
tautulliUsers.forEach((tautulliUser) => {
plexUsers.forEach((plexUser) => {
if(tautulliUser.username == plexUser.username || tautulliUser.username == plexUser.email){
matchedUsers.push({id: plexUser.id, username: plexUser.username, email: plexUser.email})
}
})
})
matchedUsers.forEach((user) => {
axios.get(`https://tautulli.link/api/v2?apikey=API-KEY&cmd=get_user_watch_time_stats&user_id=${user.user_id}&query_days=7`)
.then((watchTime) => {
// I want to add the matched user to timedUsers and add the watchTime response. Something like "timedUsers.push({...user, response: response})"
// This is the part that I can't figure out.
})
})
// Use the timedUsers array to display the results.
console.log(timedUsers)
res.json(timedUsers)
})
})
})
Use Promise.all(arrayOfPromises).then(...) to wait for an array of promises to finish.
If you ever introduce async code in a Javascript function, you always need to wait for the async response to finish, so you can only access the array inside the next .then().
Changing the entire function to use the async/await syntax can make this a little nicer to work with.
Promise.all(matchedUsers.map((user) =>
axios.get(`https://tautulli.link/api/v2?apikey=API-KEY&cmd=get_user_watch_time_stats&user_id=${user.user_id}&query_days=7`)
.then((response) => ({ ...user, response }))
).then(res => {
timedUsers = res;
}
Note the matchedUsers.map((user) => axios.get... syntax, which doesn't put a curly brace around the function body. This is an implicit Javascript return, so the map will return an array of the axios get promises.
Same for (response) => ({ ...user, response }), which is an explicit return of an object from a function. You must wrap the object in ( ) to signify it's an implicit object return.
You should use Promise.all, also I converted your route to async/await syntax as it is much easier to read and work with. It is not recommended to await in the loop it is better to push all the promises to an array and then use Promise.all to wait for the all.
app.get('/matchedusers', async(req, res) => {
const allUsers = await plexClient.getAllUsers();
const tautulliUser = await axios.get('https://tautulli.link/api/v2?apikey=API-KEY&cmd=get_users_table&length=150');
let tautulliUsers = tautulliUser.data.response.data.data
let matchedUsers = []
let timedUsers = []
tautulliUsers.forEach((tautulliUser) => {
plexUsers.forEach((plexUser) => {
if (tautulliUser.username == plexUser.username || tautulliUser.username == plexUser.email) {
matchedUsers.push({
id: plexUser.id,
username: plexUser.username,
email: plexUser.email
})
}
})
})
matchedUsers.forEach((user) => {
const response = axios.get(`https://tautulli.link/api/v2?apikey=API-KEY&cmd=get_user_watch_time_stats&user_id=${user.user_id}&query_days=7`);
timedUsers.push({ ...user,
response
});
})
const final = await Promise.all(timedUsers);
console.log(final)
res.json(final)
})
I suggest you use async/await syntax, and use Promise.all and map to resolve the request promises first then add them to timedUsers array.
app.get("/matchedusers", async (req, res) => {
const plexUsers = await plexClient.getAllUsers();
const tautulliUser = await axios.get(
"https://tautulli.link/api/v2?apikey=API-KEY&cmd=get_users_table&length=150"
);
let tautulliUsers = tautulliUser.data.response.data.data;
let matchedUsers = [];
let timedUsers = [];
// Doing a check to see if tautulli user is also a plex user.
tautulliUsers.forEach((tautulliUser) => {
plexUsers.forEach((plexUser) => {
if (
tautulliUser.username == plexUser.username ||
tautulliUser.username == plexUser.email
) {
matchedUsers.push({
id: plexUser.id,
username: plexUser.username,
email: plexUser.email,
});
}
});
});
// I want to add the matched user to timedUsers and add the watchTime response. Something like "timedUsers.push({...user, response: response})"
// This is the part that I can't figure out.
timedUsers = await Promise.all(
matchedUsers.map(async (user) => {
const response = await axios.get(
`https://tautulli.link/api/v2?apikey=API-KEY&cmd=get_user_watch_time_stats&user_id=${user.user_id}&query_days=7`
);
return { ...user, response }
})
);
// Use the timedUsers array to display the results.
console.log(timedUsers);
res.json(timedUsers);
});
I do not get any result after I run the "set( )" function to the "res" variable when running this code, meaning that the "res" variable is undefined even though the docuement gets created in firebase. I have tried .then() .catch() too and that doesn't give me any kind of result either. The document gets created and everything works, and I if I want I can just return the Promise no matter the outcome of the firebase function, but that feels like it's bad practice since Im overlooking a possible error right?
Can I somehow get a result from "set( )" function? or in some other way make sure that the "set( )" function is successful?
exports.create = async function(listId, name, link) {
const newLinkRef = db.firestore.collection('links').doc();
const data = {
id: newLinkRef.id,
listId: listId,
name: name,
link: link
};
var res = await newLinkRef.set(data);
console.log(res)
if (res.id) {
return new Promise(resolve => {resolve({error: null, linkId: res.Id})})
} else {
return new Promise(resolve => {resolve({error: "Error creating lint"})})
}
}
(I use the "set( )" function over the "add( )" funciton since I want to save the random created Id inside the object stored to, and this was the simplest way I could find to do that)
set() returns a promise, but your use of await consume that promise and leaves res as the result that the promise wraps, which is void. So undefined seems correct there.
I think you're looking for:
try {
var res = await newLinkRef.set(data);
return {error: null, linkId: newLinkRef.Id};
}
catch (e) {
return {error: "Error creating lint"}
}
Alternatively you can not use await, and you end up with:
return newLinkRef.set(data).then(() => {
return {error: null, linkId: newLinkRef.Id};
}).catch (e) => {
return {error: "Error creating lint"}
})
Been on this for over 24 hours, everything seems to work as I want but the promise keeps returning null.
[
null,
null
]
here are my codes:
let vettedBatch = currentBatch.Items.map((current) => {
getUser(current.userId).then((res) => {
// return resolve(JSON.parse(res.body));
let body = JSON.parse(res.body);
if (body.hasOwnProperty("Item")) {
return body;
} else {
//if user does not exist on the users table based on ID, lets take his transaction out of the fail-safe table
console.log(
`user with id number ${current.userId} with transaction id ${current.txId} do not exist or must have been disabled`
);
User.deleteWithdrawalTx(current.txId).then(() => {
console.log(
`transaction id ${current.txId} delete for unknown user with userId ${current.userId}`
);
});
}
});
});
You need to use Promise.all:
const data = [];
const promises = currentBatch.Items.map(async current => {
return await getUser(current.userId)
});
Promise.all(promises)
.then(res => {
res.map(item => {
let { body } = JSON.parse(item);
if (body.hasOwnProperty("Item")) {
data.push(body);
} else {
console.log('message');
}
})
})
Instead of mixing async/await and Promise syntax, I would suggest you to stick to one.
Here would be your code written fully in async/await syntax:
const getData = async () => { // async function instead of new Promise()...
return Promise.all(currentBatch.Items.map(async (current) => { // make map async and await it with Promise.all()
const res = await getUser(current.userId); // await instead of .then()
let body = JSON.parse(res.body);
if (body.hasOwnProperty("Item")) {
return body;
} else {
console.log(`user with id number ${current.userId} with transaction id ${current.txId} do not exist or must have been disabled`);
await User.deleteWithdrawalTx(current.txId); // await instead of .then()
console.log(`transaction id ${current.txId} delete for unknown user with userId ${current.userId}`);
// You should return something here too, but I dont know what you want to return, so...
}
}));
}
let vettedBatch = await getData(); // await the async function
Your problem is actually a deviation of this question: How do I return the response from an asynchronous call?. Should be fixed in my answer, but I still suggest you to check out the linked thread.
I want to fetch data for every object in an array and return an array of new objects with the previous and newly fetched data.I got stucked on getting my result array as my function is returning an array of resolved undefined promises.
I am using a flight search api thats using the apca function for fetching
export const searchApcaLocation = async (dataArr,setDeals) => {
const promises = await dataArr.map(async item => {
apca.request(item.destination);
apca.onSuccess = (data) => {
return fetch('http://localhost:3050/googlePlaceSearch',{
method:"post",
headers:{'Content-Type':'application/json'},
body:JSON.stringify({
cityName:data.airports[0].city
})
})
.then(res => res.json())
.then(imagelinkData => {
const locationObject = {
data: item,
imagelink: imagelinkData.link
}
return locationObject
})
.catch(err => console.log('error on image search',err))
};
apca.onError = (data) => {
console.log('error',data)
};
})
const results = await Promise.all(promises)
return results
}
can someone guide me please on what am I doing wrong?
edit:
as I am trying to fix it realized the problem is I am not returning anything in my map function but if trying to return the apca.onSuccess I am getting an array of functions
just return is missing before fetch function. since you're not returning your promise result it's giving undefined.
export const searchApcaLocation = async (dataArr,setDeals) => {
const promises = await dataArr.map(async item => {
apca.request(item.destination);
apca.onSuccess = (data) => {
return fetch('http://localhost:3050/googlePlaceSearch',{
method:"post",
headers:{'Content-Type':'application/json'},
body:JSON.stringify({
cityName:data.airports[0].city
})
})
.then(res => res.json())
.then(imagelinkData => {
const locationObject = {
data: item,
imagelink: imagelinkData.link
}
return locationObject
})
.catch(err => console.log('error on image search',err))
};
apca.onError = (data) => {
console.log('error',data)
};
})
const results = await Promise.all(promises)
return results
}
The issue in your case might be, that you are using async/await and then blocks together.
Let me sum up what is happening :
1) you await dataArray.map
2) within the map callback, you use the onSuccess method of apca
3) within this method you are using then blocks which won't await until you got a response.
At this point where you return the locationObject, your function already reached the return statement and tries to return results.
But results are of course undefined because they never get resolved at all.
Also, keep in mind that your function returns another promise because you used async/await which you have to resolve where you imported it.
Cheers :)