Hi this is my function i am calling this from my controller like this:
var getLastPoll = await socketModel. getPollOptionsByPollId(data.poll_id);
but i am getting empty array as result in controller but when i logged result in my model it is returning the data of array containing two objects ? where i am doing mistake can someone help?
const getPollOptionsByPollId = async (poll_id) =>
{
var querySql1 = "SELECT * FROM public.group_poll_options
WHERE option_poll_id= $1 AND
option_status = $2 ORDER BY option_id";
var queryParams1 = [poll_id, "active"];
var pollOptions = await db.query(querySql1, queryParams1);
var result = [];
if (pollOptions.rowCount != 0) {
pollOptions.rows.map(async value => {
var voteCount = await totalvotesbypolloption(poll_id, value.option_id);
console.log("voteCount",voteCount);
var data = {
option_id: value.option_id,
option_poll_id: value.option_poll_id,
option_value: value.option_value,
option_status: value.option_status,
option_created_at: value.option_created_at,
option_votes: voteCount
}
result.push(data);
});
}
return result;
}```
Using async/await when iterating over arrays with map, forEach, etc, doesn't do what you expect it to do. All iterations will finish before totalvotesbypolloption is called even once.
Replace map with with for...of:
for (const value of pollOptions.rows) {
var voteCount = await totalvotesbypolloption(poll_id, value.option_id);
console.log("voteCount",voteCount);
var data = {
option_id: value.option_id,
option_poll_id: value.option_poll_id,
option_value: value.option_value,
option_status: value.option_status,
option_created_at: value.option_created_at,
option_votes: voteCount
}
result.push(data);
}
Related
I'm working on a project where I need to filter 13 items by two different select box values, and I'm getting stuck on persisting the filter.
I have two select boxes that I've selected like so:
let pickupLocation = document.querySelector("#pa_location"); //values are 'complete-set', 'neck', 'bridge'.
let pickupType = document.querySelector("#pa_type1"); // Values are 'soapbar', 'dogear', 'short'.
What's Working:
I'm initializing an object like so:
const activeFilters = {};
To populate the values like so:
//Persist the Complete Set / Single
pickupLocation.addEventListener("change", function () {
if (pickupLocation.value === "complete-set") {
activeFilters.location = "set";
} else {
activeFilters.location = "single";
}
});
pickupType.addEventListener("change", function () {
if (pickupType.value === "soapbar") {
activeFilters.type = "soapbar";
} else if (pickupType.value === "dogear") {
activeFilters.type = "dogear";
} else {
activeFilters.type = "short";
}
});
// Returns something like
// {location: single, type: dogear}
I'm trying to filter an array of input elements by their value. I have 13 inputs each with a value containing words like set, single, dogear, soapbar etc.
Where I'm stuck:
I have a filter function that I'm trying to filter the values of these inputs by two values of the activeFilters object:
const performFilter = (covers) => {
let results;
let filteredValues = Object.values(activeFilters);
filteredValues.forEach((value) => {
results = covers.filter((cover) => cover.value.indexOf(value) !== -1);
});
return results;
};
The problem is my function is returning only one of the two words. For instance, if the my activeFilters object is {location: set, type: dogear} the filtered results array contains only one of them. Where am I going wrong?
Edit:
This function returns all inputs that match one of the activeFilters, and I apologize if I wasn't clear above, but I'd like it to match ALL of the Active Filters. Is this possible with the function below?
const performFilter = (covers) => {
let results = []; // initialise the array
let filteredValues = Object.values(activeFilters);
filteredValues.forEach((value) => {
let res = covers.filter((cover) => cover.value.indexOf(value) !== -1);
results.push(...res);
});
console.log(results);
};
CODEPEN:
Codepen!
const performFilter = (covers) => {
let results = []; // initialise the array
let filteredValues = Object.values(activeFilters);
filteredValues.forEach((value) => {
let res = covers.filter((cover) => cover.value.indexOf(value) !== -1);
// push the value it find individually
// you were overriding the previous value with result = filter()
results.push(...res);
});
return results;
};
// according to Edited question
const performFilter = (covers) => {
let results = []; // initialise the array
let filteredValues = Object.values(activeFilters);
return covers.filter((cover) => filteredValues.every(value => cover.value.indexOf(value) !== -1));
};
I'm not sure if I understood clearly your question, so feel free to comment it.
First, I suggest you to filter your covers array and inside the filtering function iterate through your selected filters. This is because the filter function returns the array already filtered and so you don't need to assign it to a result variable or things like that. So based on that, try this:
const performFilter = (covers) => {
let results;
let filteredValues = Object.values(activeFilters);
const filteredCovers = covers.filter((cover) => {
return cover.value.split("-").some((tag) => filteredValues.includes(tag))
});
console.log(filteredCovers)
};
I believe this may be an issue with async or promises, however, this concept has been a struggle for me to grasp. I have spent much time researching questions relating to papaparse and promises, but believe I am still not grasping some simple concept.
Overview
In the below code, a .csv file is gathered from the user, converted into an Object using PapaParse, then distance/duration values are added to the data from GoogleMaps Distance Matrix and finally, the intent is to return this data back to the user as a .csv containing this combined information.
In downloadCSV(), I am able to log the Object which results from getDistTime. However, I am unable to iterate over this object or send it to papa.unparse to convert to a .csv. Below the code, I have attached an image of the structure of arr within downloadCSV().
I have spent much time researching questions here, and on the papaparse repo. I would appreciate any help on how to best proceed.
Contents of arr:
Code
$("#submit").click(function(){
//REMOVE THIS LINE BEFORE LIVE OR VALIDATION WILL BE DUN GOOFED
event.preventDefault();
getData();
});
function getData(){
var csv = document.getElementById('exampleFormControlFile1').files[0];
// Parse CSV string
Papa.parse(csv, {
header: true,
complete: function(results) {
var final_rows = getDistTime(results)
downloadCSV(final_rows)
}
});
} // end getData
function downloadCSV(arr){
//console.log(arr) shows the results
// but trying to iterate over arr or unparsing shows undefined
console.log(arr)
csv = Papa.unparse(arr)
...more csv export code
}
function getDistTime(resources){
var rows = []
const promiseArr = [];
for (var i = 0; i < resources.data.length; i++) {
var origin1 = $("#citystate").val();;
var destinationA = resources.data[i]['DEMOBILIZATION CITY'] + ',' + resources.data[i]['DEMOBILIZATION STATE'];
promiseArr.push(googleRequest(origin1, destinationA));
}
Promise.all(promiseArr)
.then((resultsArr) => {
resultsArr.forEach((result, i) =>
pushToRows(resources.data[i], result, rows));
})
return rows
} // end getDistTime
function pushToRows(resources, dist_dur, rows){
resources["DISTANCE_MI"] = dist_dur[0];
resources["ACTUAL_DUR_HR"] = dist_dur[1];
resources["FINANCE_DUR_HR"] = (dist_dur[0] / 45.0).toFixed(2)
rows.push(resources)
} // end pushToRows
getDistTime is performing an async action and therefore rows is returning empty before the Promise.all has resolved as you wont have pushed any data to it until that promise resolves.
Looks like you'll need to await the result of getDistTime or change how get data works, not sure you're using async await so simplest way is to just return that Promise.all and then only download the csv once its returned and resolved in your complete callback.
for example you could do
function getData(){
var csv = document.getElementById('exampleFormControlFile1').files[0];
// Parse CSV string
Papa.parse(csv, {
header: true,
complete: function(results) {
getDistTime(results).then(finalRows => downloadCSV(finalRows));
}
});
} // end getData
function getDistTime(resources){
var rows = []
const promiseArr = [];
for (var i = 0; i < resources.data.length; i++) {
var origin1 = $("#citystate").val();;
var destinationA = resources.data[i]['DEMOBILIZATION CITY'] + ',' + resources.data[i]['DEMOBILIZATION STATE'];
promiseArr.push(googleRequest(origin1, destinationA));
}
return Promise.all(promiseArr)
.then((resultsArr) => {
resultsArr.forEach((result, i) =>
pushToRows(resources.data[i], result, rows)
);
return rows
})
} // end getDistTime
I´m trying to loop through the content of a DataSnapshot and then depending on a condition do some work FOR EACH one of the elements but currently, the ForEach is only doing the work in the first item. The "serverStatus" sometimes is waiting and sometimes in "onCall". When the first item is "onCall" does not go through the rest of the items as I think is supposed to do. Below a snapchot of where I get the information from:
And here is my function:
exports.manageCallRequests = functions.database.ref('/resquests/{userId}').onCreate((snap, context) => {
const event = snap.val();
console.log("function manageCallRequests is being called")
var rootPath = admin.database().ref();
var userOnCall = context.params.userId;
var serversRef = rootPath.child('servers');
var callRequest = event;
var userTime = callRequest["time"];
var waiting= "waiting";
//We first get all the servers in ascending order depending on the last time they were used
var serversSorted = serversRef.orderByChild('lastTimeUsed')
//Gets the children on the "serversSorted" Query
return serversSorted.once("value").then(allServers =>{
//Checks if there is any child
if(allServers.hasChildren()){
allServers.forEach(async function(server) {
//we extract the value from the server variable, this contains all the information
//about each one of the servers we have
var serverInfo = server.val();
var serverKey = server.key;
var serverNumber = serverInfo["serverNumber"];
var serverStatus = serverInfo["serverStatus"];
console.log("server status "+serverStatus)
if(serverStatus === waiting){
const setCallRequest = await serversRef.child(serverKey).child("current").child("callRequest").set(callRequest);
const removeUserOnCall = await rootPath.child("resquests").child(userOnCall).remove();
const setServerStatus = await serversRef.child(serverKey).child("serverStatus").set("onCall");
}
});
}else{
console.log("No servers available")
}
});
});
I had the same behavior because my cloud function was exited before that all iterations were executed in the forEach loop.I get rid of it using this snippet of code:
for (const doc of querySnapshot.docs) {
// Do wathever you want
// for instance:
await doc.ref.update(newData);
}
I found 2 ways of getting this done. The first one is useful if we have a DataSnapshot without any OrderBy* call, in this case, would be:
var allServers = await serversRef.once("value");
for (let serverKey of Object.keys(allServers.val())){
var server = allServers[serverKey];
//Do some work
}
We need to first get the keys of the object to then be able to extract it from within the for loop, as explained here otherwise we´ll get a "TypeError: 'x' is not iterable"
Now the problem with this particular case is that a have a DataSnapshot that was previously sorted at var serversSorted = serversRef.orderByChild('lastTimeUsed') so when we call Object.keys(allServers.val()) the value returned is no longer sorted and that´s where forEach() comes in handy. It guarantees the children of a DataSnapshot will be iterated in their query order as explained here however for some reasons when doing some async work within the forEach loop this seems not to work, that´s why I had to do this:
var serversSorted = serversRef.orderByChild('lastTimeUsed')
var allServers = await serversSorted.once("value");
//Checks if there is any children
if (allServers.hasChildren()) {
//if there is iterate through the event that was passed in containing all
// the servers
var alreadyOnCall = false;
var arrayOfServers = []
var arrayOfKeys = []
allServers.forEach(function(individualServer){
arrayOfKeys.push(individualServer.key)
arrayOfServers.push(individualServer)
})
for (var serveIndex = 0; serveIndex < arrayOfServers.length;serveIndex++){
var serverObj = arrayOfServers[serveIndex]
var serverObject = serverObj.val()
var serverKey = arrayOfKeys[serveIndex]
var serverStatus = serverObject["serverStatus"];
var serverNumber = serverObject["serverNumber"];
console.log("server info "+serverStatus+" "+serverKey);
if (serverStatus === waiting && alreadyOnCall === false) {
const setCallRequest = await serversRef.child(serverKey).child("current").child("callRequest").set(callRequest);
const removeUserOnCall = await rootPath.child("resquests").child(userOnCall).remove();
const setServerStatus = await serversRef.child(serverKey).child("serverStatus").set("onCall");
alreadyOnCall= true
console.log("Call properly set");
}
}
}
I have different document id for every loop and when I query inside the forEach loop query is working but not pushing the obj into the array
function getAllDonations() {
donations = [];
const user_session_data = sessionStorage.getItem('LoginInfo');
const parse_user_login_data = JSON.parse(user_session_data);
let TABLE_NAME = "donation_favourites";
let get_requests_qry = App.db.collection(TABLE_NAME);
get_requests_qry.where('user_id', '==', parse_user_login_data.user_id).get().then(snapshot => {
let changes = snapshot.docChanges();
changes.forEach(change => {
var one_item = change.doc.data();
let TABLE_NAME1 = "donation_requests";
let get_requests_qry1 = App.db.collection(TABLE_NAME1);
get_requests_qry1.doc(one_item.donationId).get().then(snapshot => {
donations.push(snapshot.data())
});
});
console.log("checking the data",donations.length) //this length is not coming
});
}
If you want to read the files in use forloop but it is not recommended for large loop for small loop it is ok
if you want to read files parallel use forEach
You can also do it with async and await instead forLoop
await Promise.all(changes.map(async (change) => {
var one_item = change.doc.data()
let TABLE_NAME1 = "donation_requests";
let get_requests_qry1 = App.db.collection(TABLE_NAME1);
var snapshot1 = await get_requests_qry1.doc(one_item.donationId).get()
donations.push(snapshot1.data())
}));
I need to create an array with this structure:
[
{
position: 2,
family: 9404,
part: [ 'article1', 'article2', 'article3' ]
},
{
position: 3,
family: 9405,
part: [ 'article4', 'article5', 'article6' ]
}
]
So i have a form where i select the parts that i want and send the families to get url.In the getter function i do a for to get the articles of each family and i want to query a select of articles and a select of positions. After that i try to push each array to a main array but i can't, show me undefined. How can i do this kind of operations?
I'm new with node and express and this is the first time that i have to do that.
My code:
getFamilies(req, res)
{
console.log(req.params.data);
var parsedData = JSON.parse(req.params.data);
var compounds = parsedData[0].compounds;
var supplier = parsedData[0].supplier;
var families = parsedData[0].families;
console.log(parsedData[0].compounds.length);
var position = [];
var data = [];
var parts = [];
for (var i = 0; i < compounds.length; i++)
{
parts.push(request.query("SELECT st.ref, st.design FROM st WHERE familia ='"+families[i]+"'"));
position.push(request.query("SELECT u_order FROM u_part WHERE u_familia='"+families[i]+"'"));
}
return Promise.all(parts, position, families).then(function(listOfResults)
{
//add parts, position and families to data[]
var data = [];
//console.log(data);
console.log(listOfResults);
console.log("done");
//return listOfResults;
res.render('view2', {teste: data});
}).catch(function(err)
{
// ... query error checks
console.log(err);
});
}
In promise just print the first parameter "parts" and if i put the [parts, position, families] give me promise pending.
And how can i put the data in the structure that i show above.
parseData:
[
{
"compounds": ["8"],
"supplier": ["sup"],
"families": ["9305"]
}
]
Please teach me how can i do this kind of operations.
Thank you
Not sure why you're passing families to Promise.all families seems to just be an array of data from taken from the query
Promise.all takes an array of promises in input, and you're passing an array of arrays of promises and of data...
you should never build SQL queries like this. This is a big flaw for SQL injection (but that's another question)
So do:
Promise.all([...parts, ...position]) or if you're not using ES6 syntax Promise.all(parts.concat(position))
and fix your SQL!
====
Final code could look like:
getFamilies = (req, res) => {
var families = JSON.parse(req.params.data)[0].families;
var positions = [];
var data = [];
var parts = [];
families.forEach(family => {
// see http://stackoverflow.com/a/7760578/2054629 for mysql_real_escape_string
parts.push(request.query("SELECT st.ref, st.design FROM st WHERE familia ='"+mysql_real_escape_string(family)+"'"));
positions.push(request.query("SELECT u_order FROM u_part WHERE u_familia='"+mysql_real_escape_string(family)+"'"));
});
return Promise.all([Promise.all(parts), Promise.all(positions)]).then(listOfResults => {
var [partResult, positionResult] = listOfResults;
var data = families.map((family, i) => {
var pos = positionResult[i];
var parts = partResult[i];
return {family: family, position: pos, parts: parts};
});
res.render('view2', {teste: data});
}).catch(err => {
// ... query error checks
console.log(err);
});
};
You incorrectly use Promise.all, it takes array of promises
return Promise.all([Promise.all(parts), Promise.all(position)]).then(function(listOfResults){
var partResult = listOfResults[0];
var positionResult = listOfResults[1];
var data = [];
for (var i=0; i<families.length; i++) {
var family = families[i];
var pos = positionResult[i];
var parts = partResult; // logic to extract parts for current family
data.push({family: family, position: pos, parts: parts})
}
console.log(data);
})
Promise.all() takes an array of promises, it looks like you are passing multiple arrays.