Below is my code.I am unable resolve the o/p.How to resolve in async and await.I am trying to get data from other collection and pass it to existing filtered collection
exports.listStatus = async (root, { _id, start, limit }) => {
var user = await db.User.find({ _id: _id })
let list = user[0].savedUsers
var blocked = user[0].blockedUsers
var listAll = list.push(_id)
let listOfStatus = await db.Status.find({ userId: { $in: list }, reportStatus: { $ne: _id }, _id: { $nin: blocked } });
let array;
let leng = listOfStatus.length
let statusCommentsArray
var arrayStatus = [];
listOfStatus.forEach((status, key) => {
let promise = new Promise((resolve, reject) => {
var obj = {}
var statusId = status._id
var listOfLiked = status.like
let likeCount = listOfLiked.length
var sortedList = listOfLiked.sort({ createdDate: -1 })
obj.likeCount = likeCount
db.Comment.find({ statusId: statusId }, (err, statusCommentsList) => {
var statusCommentsCount = statusCommentsList.length
var sortedList = statusCommentsList.sort({ createdDate: -1 })
if (statusCommentsCount >= 3) {
statusCommentsArray = sortedList
}
else {
statusCommentsArray = sortedList.slice(0, 3)
}
obj.statusCommentsCount = statusCommentsCount
obj.statusCommentsArray = statusCommentsArray
arrayStatus.push(obj)
leng--;
if (leng == 0) {
resolve(arrayStatus)
}
})
})
promise.then((response) => {
return Promise.resolve(response)
})
})
}
Related
How can I pass the returned coin object from the displayCurrencies function to the getCoinId function to use it as a parameter in the API call for retrieving the specific coin data?
this is the function i created to return the value:
let returnID = (value) => {
return value;
};
this is the function that i want to return coin from:
let displayCurrencies = async () => {
let coinsContainer = document.querySelector(`.coins`);
try {
let coins = await getData();
let coinsArray = [];
let coinElement;
for (const coin of coins) {
coinElement = coin;
if (coinsArray.length > 20) {
break;
}
coinsArray.push(coin);
// create Nodes
let coinDisplay = createElement(`li`, `coin`);
let coinSymbolElement = createElement(`p`, `coinSymbol`);
let coinIDElement = createElement(`p`, `coinID`);
// set Values
coinSymbolElement.innerHTML = coin.symbol;
coinIDElement.innerHTML = coin.id;
// append
coinDisplay.append(coinSymbolElement, coinIDElement);
coinsContainer.appendChild(coinDisplay);
coinDisplay.addEventListener(`click`, () => {
openModal();
returnID(coin);
});
}
let returnCoin = returnID
coinDisplay.addEventListener(`click`, () => {
console.log(returnCoin);
});
console.log(returnCoin);
} catch (error) {
console.log(error);
}
};
and last, this is the function that i want to use the returned value at:
displayCurrencies();
let getCoinId = async () => {
let coinID = await displayCurrencies();
let currencyData = `https://api.coingecko.com/api/v3/coins/${coinID}`;
let responseData = await fetch(currencyData);
let dataOfCoins = await responseData.json();
console.log(dataOfCoins);
};
You can simply add an onclick event for each element, and when the call-back is called you invoke the getCoinID function passing the coinID as a parameter.
A simple example:
<ul class="coins">
</ul>
<script>
function addOnClick() {
let coinsContainer = document.querySelector('.coins');
let coins = [
{ id: 1, symbol: 'bitcoin' },
{ id: 3, symbol: 'brazil-fan-token' },
{ id: 4, symbol: 'celo-euro' },
]
for (const coin of coins) {
let coinDisplay = document.createElement('li')
let coinSymbolElement = document.createElement('p')
let coinIDElement = document.createElement('p')
coinSymbolElement.innerHTML = coin.symbol
coinIDElement.innerHTML = coin.id
coinDisplay.appendChild(coinIDElement)
coinDisplay.appendChild(coinSymbolElement)
coinsContainer.appendChild(coinDisplay)
coinDisplay.addEventListener('click', () => {
getCoinID(coin.symbol)
})
}
}
async function getCoinID(coinID) {
let currencyData = `https://api.coingecko.com/api/v3/coins/${coinID}`
let responseData = await fetch(currencyData)
let dataOfCoins = await responseData.json()
console.log(dataOfCoins)
}
addOnClick()
</script>
This question already has answers here:
JavaScript array .reduce with async/await
(11 answers)
Closed 6 months ago.
I need to fetch values from another API using the guid inside this particular array, then group them together (hence I used reduce Javascript in this case)
However, I could not get those values sumEstimatedHours and sumWorkedHours as expected. Can someone suggest a method please?
export const groupProjectsByPM = (listOfProjects) => {
const dir = "./json";
const estimatedHours = fs.existsSync(dir)
? JSON.parse(fs.readFileSync("./json/phases.json", "utf-8"))
: null;
let sumWorkedHours, sumEstimatedHours;
const groupedProjects = listOfProjects?.reduce(
(
group,
{
guid,
projectOwner: { name: POName },
name,
customer: { name: customerName },
deadline,
calculatedCompletionPercentage,
}
) => {
listOfProjects.map(async (element, index) => {
// const element = listOfProjects[index];
sumWorkedHours = await getWorkhoursByProject(element?.guid).then(
(res) => {
return res.reduce((acc, cur) => {
return acc + cur.quantity;
}, 0);
}
);
const filteredEstimatedHours = estimatedHours.filter(
(item) => item.project.guid === element.guid
);
sumEstimatedHours = filteredEstimatedHours.reduce((acc, cur) => {
return acc + cur.workHoursEstimate;
}, 0);
group[POName] = group[POName] || [];
group[POName].push({
guid,
name,
POName,
customerName,
deadline,
calculatedCompletionPercentage,
sumEstimatedHours,
sumWorkedHours,
});
return group;
});
return group;
},
[]
);
return groupedProjects;
};
here is an example of async/await inside reduce:
let's assume that we have an array of numbers
const arrayOfNumbers = [2,4,5,7,6,1];
We are going to sum them using reduce function:
const sumReducer = async () => {
const sum = await arrayOfNumbers.reduce(async (promisedSum, num) => {
const sumAcc = await promisedSum
// any promised function can be called here..
return sumAcc + num
}, 0)
console.log(sum)
}
So the trick is to remember to await the accumulator inside the reduce function
export const groupProjectsByPM = async (listOfProjects) => {
const dir = "./json";
const estimatedHours = fs.existsSync(dir)
? JSON.parse(fs.readFileSync("./json/phases.json", "utf-8"))
: null;
let sumWorkedHours, sumEstimatedHours;
const groupedProjects = await listOfProjects?.reduce(
async (
promisedGroup,
{
guid,
projectOwner: { name: POName },
name,
customer: { name: customerName },
deadline,
calculatedCompletionPercentage,
}
) => {
listOfProjects.map(async (element, index) => {
//accumulator in your case is group
const group = await promisedGroup;
// const element = listOfProjects[index];
sumWorkedHours = await getWorkhoursByProject(element?.guid).then(
(res) => {
return res.reduce((acc, cur) => {
return acc + cur.quantity;
}, 0);
}
);
const filteredEstimatedHours = estimatedHours.filter(
(item) => item.project.guid === element.guid
);
sumEstimatedHours = filteredEstimatedHours.reduce((acc, cur) => {
return acc + cur.workHoursEstimate;
}, 0);
group[POName] = group[POName] || [];
group[POName].push({
guid,
name,
POName,
customerName,
deadline,
calculatedCompletionPercentage,
sumEstimatedHours,
sumWorkedHours,
});
return group;
});
return group;
},
[]
);
return groupedProjects;
};
Best of luck ...
I am trying to run a query, inside AXIOS which gets data from a 3rd party URL. Then uses some of that data to search our mongoDB database.
However it seems it won't update var total = 0
While the query below does function correctly, the return result won't allow me to set that it to the query.
Promise.all(arr.forEach( async (id,index) => {
//(CODE REMOVED JUST TO GET THIS FUNCTION TO WORK)
const search = await geoLocation.find({
'location': {
'$geoWithin': {
'$box': [
[-35.2418503, -13.5076852], [112.8656697, 129.0020486]
]
}
}}).toArray();
total = search.length;
}));
See the full code below
var array = [];
var pointarray = []
var total = 0;
areas.forEach((id,index) => {
if(id.type == "Point"){
pointarray[index] = "N"+id.id;
}else{
array[index] = "R"+id.id;
}
});
var arraySearch = "https://nominatim.openstreetmap.org/lookup?osm_ids="+array.toString()+"&polygon_geojson=1&bbox=1&format=json";
var pointSearch = "https://nominatim.openstreetmap.org/lookup?osm_ids="+pointarray.toString()+"&polygon_geojson=1&bbox=0&format=json"
const requestOne = axios.get(arraySearch);
const requestTwo = axios.get(pointSearch);
axios.all([requestOne, requestTwo])
.then(axios.spread((...responses) => {
const responseOne = responses[0]
const responseTwo = responses[1]
/*
process the responses and return in an array accordingly.
*/
return [
responseOne.data,
responseTwo.data,
];
}))
.then(arr => {
Promise.all(arr.forEach( async (id,index) => {
//const middleIndex = id[index].boundingbox.length / 2;
//const firstHalf = id[index].boundingbox.splice(0, middleIndex);
//const secondHalf = id[index].boundingbox.splice(-middleIndex);
//res.send(secondHalf[0]);
const query = [{
$match: {
location: {
$geoWithin: {$box:[[Number(firstHalf[0]),Number(firstHalf[1])],[Number(secondHalf[0]),Number(secondHalf[1])]]
}
}
}
},{
$count: 'id'
}]
const search = await geoLocation.find({
'location': {
'$geoWithin': {
'$box': [
[-35.2418503, -13.5076852], [112.8656697, 129.0020486]
]
}
}}).toArray();
total = search.length;
// total = search.length;
// const search = geoLocation.aggregate(query).toArray.length;
}));
})
.catch(errors => {
console.log("ERRORS", errors);
})
.then(function () {
res.send(total);
});
const generatePropertyAmenities = async (property) => {
let result = [];
property.amenities.map(async (res, key) => {
/**
* Get the amenities type id, creates it if it doesn't exist
* const type_existed_before: defines if the type already existed
*/
let type_id = null;
const type_existed_before = await strapi
.query("amenities-categories")
.findOne({ name: res.type.trim() });
if (type_existed_before) type_id = type_existed_before.id;
else
type_id = await strapi
.query("amenities-categories")
.create({ name: res.type }).id;
res.items.map(async (amenity) => {
const amenity_exists = await strapi
.query("amenities")
.findOne({ name: amenity.name.trim() });
if (amenity_exists) {
// console.log(amenity_exists)
if (
!type_existed_before ||
(type_existed_before &&
!amenity_exists.amenities_categories.find((x) => x === type_id))
) {
await strapi.query("amenities").update(
{ id: amenity_exists.id },
{
amenities_categories: [
...amenity_exists.amenities_categories,
type_id,
],
}
);
}
result = [...result, amenity_exists.id];
} else {
result = [
...result,
await strapi
.query("amenities")
.create({
name: amenity.name.trim(),
amenities_categories: [type_id],
}).id,
];
}
});
});
console.log(result);
return result;
};
result is always empty, am I missing something here ? I really don't see what I'm doing wrong. I checked everything, amenity_exists.id is correct, everything seems correct but something is not I really need some help here guys
Ok so I managed to make it work, I don't think I can explain why and how exactly it works I may need some explanations from you guys, but here's my fix:
const generatePropertyAmenities = async (property) => {
const getAmenityCategoryId = (item) =>
new Promise(async (resolve, reject) => {
const type_existed_before = await strapi
.query("amenities-categories")
.findOne({ name: item.type.trim() });
if (type_existed_before)
resolve({
type_id: type_existed_before.id,
type_existed_before: false,
});
else
resolve({
type_id: await strapi
.query("amenities-categories")
.create({ name: item.type }).id,
type_existed_before: false,
});
});
const getAmenity = (amenity, type_id, type_existed_before) =>
new Promise(async (resolve, reject) => {
const amenity_exists = await strapi
.query("amenities")
.findOne({ name: amenity.name.trim() });
if (amenity_exists) {
// console.log(amenity_exists)
if (
!type_existed_before ||
(type_existed_before &&
!amenity_exists.amenities_categories.find((x) => x === type_id))
) {
await strapi.query("amenities").update(
{ id: amenity_exists.id },
{
amenities_categories: [
...amenity_exists.amenities_categories,
type_id,
],
}
);
}
resolve(amenity_exists.id);
} else {
resolve(
await strapi.query("amenities").create({
name: amenity.name.trim(),
amenities_categories: [type_id],
}).id
);
}
});
const createArrayOfAmenities = () =>
new Promise(async (resolve, reject) => {
let ret = [];
for (let index = 0; index < property.amenities.length; index++) {
const element = property.amenities[index];
let { type_id, type_existed_before } = await getAmenityCategoryId(
element
);
for (let k = 0; k < element.items.length; k++) {
const amenity = element.items[k];
ret = [
...ret,
await getAmenity(amenity, type_id, type_existed_before),
];
}
}
resolve(ret)
});
return await createArrayOfAmenities();
};
Try
await res.items.map(async ...
forgive me the question.
I'm not used to node and sync / await
I have the following function which queries a mongodb returning a json, I'm saving that return on redis.
So far so good.
findLightnings: async (request, h) => {
const q = request.query.q.split(':');
const index = q[0];
const value = q[1].split(',');
const dateInit = new Date(request.query.dateInit);
const dateEnd = new Date(request.query.dateEnd);
const page = request.query.page;
const distance = request.query.distance;
const redis = require('redis');
const client = redis.createClient();
let limit = 300;
let filter = {
$and: [{
data: {
$gte: dateInit.toISOString(),
$lte: dateEnd.toISOString()
}
}]
}
if (index === 'latlng') {
filter['$and'][0]['geo.coordinates'] = {
$near: {
$geometry: {
type: 'Point',
coordinates: value.map(Number),
$minDistance: 0,
$maxDistance: distance
}
}
}
limit = 100;
} else {
filter['$and'][0][`cidade.${index}`] = {
$in: value
}
}
return client.get('elektro', async (err, reply) => {
let resp = null;
if (reply) {
console.log(reply); //<<<<<<<< Return Json OK
resp = reply // <<<<<<<<<< Return TRUE in json's place
} else {
console.log('db')
const query = await Lightning.find(filter).sort('data').skip(page*limit).limit(limit).exec();
client.set('elektro', JSON.stringify(query));
client.expire('elektro', 3600);
resp = query
}
return JSON.stringify(resp);
})
}
The problem is time to recover this data from the redis.
In the console log json appears normal, how much tento returns that value for the main function it comes 'TRUE' and not the json saved in redis.
Someone can give me a helping hand on this.
I really need this function.
const redis = require('redis');
const client = redis.createClient(6379);
const bluebird = require("bluebird");
bluebird.promisifyAll(redis.RedisClient.prototype);
bluebird.promisifyAll(redis.Multi.prototype);
const redisdata = await client.getAsync("user:photos");
if (redisdata) {
console.log(`cache EXISTS`)
return res.json({ source: 'cache', data: JSON.parse(redisdata) })
}
I was able to solve the problem with the redis client.getAsync().
which already has a native async function:
source: Node-redis
The final code is as follows:
findLightnings: async (request, h) => {
const q = request.query.q.split(':');
const index = q[0];
const value = q[1].split(',');
const dateInit = new Date(request.query.dateInit);
const dateEnd = new Date(request.query.dateEnd);
const page = request.query.page;
const distance = request.query.distance;
let limit = 300;
let filter = {
$and: [{
data: {
$gte: dateInit.toISOString(),
$lte: dateEnd.toISOString()
}
}]
}
if (index === 'latlng') {
filter['$and'][0]['geo.coordinates'] = {
$near: {
$geometry: {
type: 'Point',
coordinates: value.map(Number),
$minDistance: 0,
$maxDistance: distance
}
}
}
limit = 100;
} else {
filter['$and'][0][`cidade.${index}`] = {
$in: value
}
}
return getAsync('findLightnings'+ '/' + request.query.q + '/' + request.query.dateInit + '/' + request.query.dateEnd).then(async (res) => {
if(res){
console.log('Fonte Dados => redis')
return res
}else{
console.log('Fonte Dados => db')
try {
const query = await Lightning.find(filter).sort('data').exec();//.skip(page*limit).limit(limit).exec();
client.set('findLightnings'+ '/' + request.query.q + '/' + request.query.dateInit + '/' + request.query.dateEnd, JSON.stringify(query));
return query;
} catch (err) {
return Boom.badData(err);
}
}
client.close();
});
},