Unable to return result from promise - javascript

I am trying to read some data from 2 different tables and parse a CSV file before rendering an ejs file.
I can get the data from both tables and from the CSV file but I seem to be unable to return the result.
Pretty sure this is a problem with the way I handle async execution but I fail to see what I am doing wrong.
I've spent the last 2 days reading about this (including the threads around here) and browsing but somehow the answer still escapes me.
First file - usercms.js
app.get('/userscms', function(req, res)
{
existingUsers.getExistingUsers()
.then(function(appUsers)
{
//global users array
//I can display these in my ejs file
globalAppUsers = appUsers;
})
.then(existingUsersAttributesQlik.getExistingUsersAttributesQlik())
.then(function(usersQlikAttributes)
{
//global user attributes array
//undefined data
globalUsersQlikAttributes = usersQlikAttributes;
})
.then(existingSuppliers.parseSuppliersCSV())
.then(function(supplierData)
{
//the result I am expecting
//this prints undefined
console.log(supplierData);
}).then(function()
{
res.render('userscms.ejs',
{
users: globalAppUsers,
attributes: globalUsersQlikAttributes
});
});
});
Second function - getxistingUsers.js (identical to the getExistingUsersAttributesQlik, except for the query)
var userData = [];
var appUsers = [];
(function (exports)
{
exports.getExistingUsers = function ()
{
return promisemysql.createConnection(dbconfig.development).then(function(conn)
{
var result = conn.query("SELECT id, username, firstName, lastName, email, phone, lastLogin, isAdmin, isValid, isPhoneValid, accountCreationDateTime FROM Users");
conn.end();
return result;
}).then(function(rows)
{
return rows;
}).then(function(rows)
{
if (rows.length)
{
userData = [];
appUsers = [];
rows.forEach(function (elem)
{
userData.push(_.toArray(elem));
});
for (i = 0; i < userData.length; i++)
{
var appUser = new appUserModel.AppUser(
userData[i][0],
userData[i][1],
userData[i][2],
userData[i][3],
userData[i][4],
userData[i][5],
userData[i][6],
userData[i][7],
userData[i][8],
userData[i][9],
userData[i][10]);
appUsers.push(_.toArray(appUser));
}
return appUsers;
}
else
{
console.log("NOPE");
return null;
}
}).then(function(appUsers)
{
console.log(appUsers);
return appUsers;
});
};
})(typeof exports === 'undefined' ? this['getExistingUsers'] = {} : exports);
Third file - parseSuppliersCSV.js
var supplierData = [];
var suppliersData = [];
var csvCount = 0;
(function (exports)
{
exports.parseSuppliersCSV = function ()
{
return new Promise(function(resolve, reject)
{
var fileStream = fs.createReadStream("myCSV.csv");
var parser = fastCsv();
csvCount = 0;
supplierData = [];
suppliersData = [];
fileStream
.on("readable", function ()
{
var data;
while ((data = fileStream.read()) !== null)
{
parser.write(data);
}
})
.on("end", function ()
{
parser.end();
});
parser
.on("readable", function ()
{
var data;
while ((data = parser.read()) !== null)
{
if(csvCount >= 1)
{
csvCount++;
var arrayOfStrings = data[0].split(';');
var supplier = new supplierModel.Supplier(arrayOfStrings[0],arrayOfStrings[1]);
suppliersData.push(_.toArray(supplier));
}
else
{
csvCount++;
}
}
})
.on("end", function ()
{
console.log("done");
//all OK here
console.log(suppliersData);
//this doesn't seem to return anything
return suppliersData;
});
});
};
})(typeof exports === 'undefined' ? this['parseSuppliersCSV'] = {} : exports);
Any ideas what I am doing wrong? Am I approaching this the wrong way?

I'll take a guess here and assume the promise you created should resolve to something...instead of returning a value.
.on("end", function ()
{
console.log("done");
//all OK here
console.log(suppliersData);
//this doesn't seem to return anything
return resolve(suppliersData);
});

Related

Async call in javascript For Loop not working

I have a callback function inside a loop here for (var res in results) {
but it seems the loop is not waiting for the async call. When I am calling self.callTestOutputData(test_output_url) here, the loop is not waiting fpor the response but continuing for the next iteration and I am losing out the value to push into obj.requistion_number = testOutputResponse.value;
Please note : var results = response.results Here results is an array of Json objects.
Edit 1 : I tried forEach but that didn't work .
results.forEach(res => {
var obj = {}
obj.ferp = res.name;
// your code...
})
Original Code:
self.downloadDailyExcelProcurement = function (filters, excelTmpArr) {
self.disableExcelDownloadProcurement(true);
$('.useCaseExcelButtonProcurement .oj-button-button .oj-button-label')[0].style.backgroundColor = "gray";
$('.useCaseExcelButtonProcurement .oj-button-button .oj-button-label .demo-download-icon-24')[0].style.color = "#D8D8D8";
var payload = {};
if (typeof filters === "string") {
var fill = filters;
} else {
var fill = self.sendFilters();
if(self.app() === "fusion"){
fill += '&module=Procurement';
}else if (self.app() === "o2r"){
fill += '&module=O2r';
}
}
if(fill.includes("%3A")){
fill = fill.replace(/%3A/g, ':');
}
payload.Endpoint = 'executions/testcollection/' + fill;
//console.log(payload.Endpoint)
payload.BeforeSend = function (xhr) {
xhr.setRequestHeader('Authorization', 'Basic ' + btoa('guest:oracle123'));
$(".custom-loader-circle").show();
};
payload.OnSuccess = function (response) {
var results = response.results;
for (var res in results) {
var obj = {}
obj.ferp = results[res].name;
obj.po = "NA"
obj.receipt_no = "NA"
var test_output_url = results[res].reference_test_cases[0].automation_tests[0].test_outputs[0]
$.when(self.callTestOutputData(test_output_url)).done(function (testOutputResponse) {
if(testOutputResponse)
obj.requistion_number = testOutputResponse.value;
else {
obj.requistion_number = "NA";
}
self.excelTmpArr().push(obj);
});
}
else {
self.excelTmpArr().push(obj);
}
}
if (response.next) {
filters = ((response.next).split('testcollection'))[1];
if (filters[0] === "/") {
var test = filters.slice(1, filters.length);
}
self.downloadDailyExcelProcurement(test, self.excelTmpArr());
} else {
if (results.length === 0) {
$(".custom-loader-circle").hide();
self.disableExcelDownloadProcurement(false);
$('.useCaseExcelButtonProcurement .oj-button-button .oj-button-label')[0].style.backgroundColor = "#4d0000";
$('.useCaseExcelButtonProcurement .oj-button-button .oj-button-label .demo-download-icon-24')[0].style.color = "white";
showMessage(self.messages, "No Data to Download", '', 'info');
} else {
self.formatForExcel(self.excelTmpArr(), fill, "Procurement");
}
}
};
payload.OnError = function (data) {
showMessage(self.messages, data.status, data.statusText, 'error');
$(".custom-loader-circle").hide();
};
getData(payload);
}
Try using async and await :
async function asyncCall () {
// call here
}
for (var res in results) {
const response = await asyncCall();
}
var results = response.results;
if(result.length > 0){
results.map((data,index)=>{
//write your code here
})
}
This will help you ..
Use forEach() to iterate since it creates its own function closure:
results.forEach(res => {
var obj = {}
obj.ferp = res.name;
// your code...
})

Require in forloop not working as expected

I have the following code:
var tableRequiredList = [];
var requireListPath = [
'./slimShady.js',
'./chickaChicka.js'
];
var getRequires = function() {
for (var i = 0; i < requireListPath.length; i++) {
((requireNamePath) => {
try {
console.log("INSIDE LOOP RESULT", i, require(requireNamePath)().getName()); // Outputs correct result for the index ("ChickaChicka")
tableRequiredList.push({ "name": requireNamePath, "theReq": require(requireNamePath)() });
// tableRequiredList.push({ "name": requireNamePath, "theReq": ((thePath) => { return require(thePath)(); })(requireNamePath) }); // This also doesn't seem to work.
} catch(err) {
console.log("Error importing: ", requireNamePath, " Error reported: ", err);
}
})(requireListPath[i]);
};
console.log("NAME", tableRequiredList[0].name); // Outputs the correct result ("slimShady.js")
console.log("FUNC NAME", tableRequiredList[0].theReq.getName()); // Always outputs the last item in requireListPath list ("ChickaChicka")
};
getRequires();
Example Module 1 - slimShady.js
((module) => {
module.exports = {};
var exampleModuleName1 = function() {
this.getName = function() {
return 'myNameIsSlimShady';
};
return this;
};
module.exports = exampleModuleName1;
})(module);
Example Module 2 - chickaChicka.js
((module) => {
module.exports = {};
var exampleModuleName2 = function() {
this.getName = function() {
return 'ChickaChicka';
};
return this;
};
module.exports = exampleModuleName2;
})(module);
Why does it output:
INSIDE LOOP RESULT 0 myNameIsSlimShady
INSIDE LOOP RESULT 1 ChickaChicka
NAME ./slimShady.js
FUNC NAME ChickaChicka
When it should be outputting the first index of the tableRequiredList array? This seems to only happen with require(). I have tried using map and forEach, along with the closure example above. All have the same results.
Thanks to #liliscent, I figured it out.
Just needed to change modules to this:
((module) => {
module.exports = {};
var exampleModuleName2 = function() {
var retr = {};
retr.getName = function() {
return 'ChickaChicka';
};
return retr;
};
module.exports = exampleModuleName2;
})(module);

meteor: conditional subscription in template level

i reuse the same template in other route with different data argument but using the same publication...
if i do normal pub/sub, the data being published as expected. but when i do conditional pub/sub like below, i fail to subscribe the data. console log return empty array,,,
server/publication.js
Meteor.publish('ACStats', function(cId, uId) {
var selectors = {cId:cId, uId:uId};
var options = {
fields: {qId:0}
};
return ACStats.find(selectors,options);
});
client/onCreated
Template.channelList.onCreated(function() {
this.disable = new ReactiveVar('');
if (FlowRouter.getRouteName() === 'profile') {
var self = this;
self.autorun(function() {
var penName = FlowRouter.getParam('penName');
var u = Meteor.users.findOne({slugName:penName});
if (u) {var uId = u._id;}
Meteor.subscribe('ACStats', null, uId);
});
} else{
var self = this;
self.autorun(function() {
var channelName = FlowRouter.getParam('channel');
var c = Channels.findOne({title:channelName});
if (c) {var cId = c._id;}
Meteor.subscribe('ACStats', cId, null);
});
}
});
console
ACStats.find().fetch() //return empty array
anyone have figured out my mistake ..??
thank You so much....
You can make two publications:
Meteor.publish ('ACStatsChannels', cId, function() {
});
Meteor.publish ('ACStatsUsers', uId, function() {
})
And then subscribe like this:
Template.channelList.onCreated(function() {
this.disable = new ReactiveVar('');
var self = this;
self.autorun(function() {
if (FlowRouter.getRouteName() === 'profile') {
var penName = FlowRouter.getParam('penName');
self.subscribe('ACStatsUsers', penName);
} else {
var channelName = FlowRouter.getParam('channel');
self.subscribe('ACStatsChannels', channelName);
}
});
});

How to create a class which has a property and a function with same name

I want to be able to call simultaneously something like this in javascript:
classInstance.room.get('criteria');
classInstance.room('criteria').remove('criteria');
classInstance.room().update('criteria');
I have seen implemented something similar at shouldjs
should(10).be.a.Number();
(10).should.be.a.Number();
Updated
I have the following code:
function connectToDatabase() {
var server = orientDB(dbConfig.server);
var db = server.use(dbConfig.database);
db.on("endQuery", function onDbEndQuery() {
db.server.close();
});
return db;
}
var DbSet = function DbSet(name) {
return {
list: function list(where, select, order) {
where = where || true;
select = _.isString(select) || _.isArray(select) ? select : '*';
order = _.isString(order) || _.isArray(order) ? order : 'rid';
return connectToDatabase()
.select(select)
.from(name)
.where(where)
.order(order)
.all();
},
get: function get(where, select) {
where = where || true;
select = _.isString(select) || _.isArray(select) ? select : '*';
return connectToDatabase()
.select(select)
.from(name)
.where(where)
.all()
.then(function onResults(results) {
if (results.length > 1) {
throw new Error('multiple results');
}
return results[0];
});
},
create: function create(record) {
return connectToDatabase()
.insert()
.into(name)
.set(record)
.one();
},
update: function update(where, changes) {
where = where || true;
return connectToDatabase()
.update(name)
.set(changes)
.where(where)
.scalar();
},
remove: function remove(where) {
where = where || true;
return connectToDatabase()
.delete('VERTEX', name)
.where(where)
.scalar();
}
};
};
var db = function getDb() {
return {
room: new DbSet('Room'),
invitation: new DbSet('Invitation'),
participant: new DbSet('Participant'),
};
};
module.exports = db();
And I want to change the code be able to execute the following code:
var db=require('path/to/database');
var room = db.room.get({name:'room 1'});
var sameRoom = db.room({name:'room 1'}).get();
db.room.create({name:'second room'});
db.room({name:'second room'}).create();
//same for methods list and delete
var room = db.room.list({status:'active'});
var sameRooms = db.room({status:'active'}).list();
db.room.update({name:'second room'},{status:'inactive'});
db.room({name:'second room'}).update({status:'inactive'});
I want to be able to execute the same code for Invitation and Participant too.
We need more information as to what those functions do, but this code presents those features.
Klass = function () {};
Klass.prototype.room = function () {
....
return {
get: function () {...},
remove: function () {...},
update: function () {...}
}
};
Klass.prototype.room.get = function () {...};
classInstance = new Klass();

Javascript Returning from within a nested function

I'm trying to return the output of the randomizer function within a route... I keep getting 'undefined' - but no idea what I'm doing wrong...
var randomizer = function() {
// A load of stuff happens here.. and functions that are needed by the pullOut function (I've removed for brevity)
var pullOut = function(pick) {
if (playerList.length !== pick) {
var random_item = getRandomItem(list, weight);
if (playerList.indexOf(random_item) == -1) { // doesn't exist. So add to array.
playerList.push(random_item);
}
pullOut(pick);
} else {
console.log(playerList)
return playerList;
}
}
return pullOut(pick);
}
router.route('/ordercreated')
.post(function(req, res) {
var orderedItems = req.body.line_items;
// I foreach through all the items - calling the randomizer function on each one...
_.forEach(orderedItems, function(n) {
Pack.findOne({
'product_id': n.variant_id
}, function(err, pack) {
if (err) {
return res.send(err);
}
if (pack) {
var list = [];
var weight = [];
_.forEach(pack.playerData, function(n) {
list.push(n.name);
weight.push(parseInt(n.chance));
});
console.log('randomizing', randomizer(pack.title, list, weight, n.qty, pack.pick));
}
});
});
res.sendStatus(200);
})
Your "pullOut" function calls itself, but it throws away the result of that call.
var randomizer = function() {
// A load of stuff happens here.. and functions that are needed by the
// pullOut function (I've removed for brevity)
var pullOut = function(pick) {
if (playerList.length !== pick) {
var random_item = getRandomItem(list, weight);
if (playerList.indexOf(random_item) == -1) { // doesn't exist. So add to array.
playerList.push(random_item);
}
return pullOut(pick); // <--- add return
} else {
console.log(playerList)
return playerList;
}
}
return pullOut(pick);
}
Without that return, when the function took that path through the main if statement it would return undefined.

Categories