Passing data back from a promise resolve call - javascript

I am trying to call a function and then return some data back in the returned parameter and I am using promises but I can not get my returned data back.
I have the calls here :
fbUserInfo(recipientId,req).then(function(){
getSessionData(FB_ID).then(function(rowsJson){
console.log('%%%%%%%%' + JSON.stringify(rowsJson));
})
})
My functions are defined here
/*
* FUNCTION: getSessionData
* PURPOSE : Get the session data into global variables
*/
function getSessionData(FB_ID){
var gender, user_name;
var rowsJson = {'gender': gender, 'user_name': user_name };
console.log('START to get client data');
return new Promise((resolve,reject) => {
client.hmget(FB_ID,'gender',function(err,reply){
rowsJson.gender = reply;
console.log('^^^ gender :' + rowsJson.gender);
});
client.hmget(FB_ID,'name',function(err,reply){
rowsJson.user_name = reply;
console.log('^^^ user_name :' + rowsJson.user_name);
});
resolve(rowsJson);
}); // return
} // getSessionData
/*
* FUNCTION: fbUserInfo
* PURPOSE : Called once when displaying the user welcome message
* to get the Facebook user details an place them in the
* session if they dont already exist
*/
function fbUserInfo(id,req) {
return new Promise((resolve, reject) => {
var url = 'https://graph.facebook.com/v2.6/' + id;
console.log('^^^^ url ' + url);
const options = {
method: 'GET',
uri: url,
qs: {
fields: 'first_name,last_name,profile_pic,locale,timezone,gender',
access_token: FB_PAGE_TOKEN1
},
json: true // JSON stringifies the body automatically
}
console.log('^^^ CALL RQ');
rp(options)
.then((response) => {
console.log('Suucess' + JSON.stringify(response.gender));
var profile_pic = JSON.stringify(response.profile_pic).replace(/\"/g, "");
console.log('1. profile_pic:' + profile_pic);
// Now find the position of the 6th '/'
var startPos = nth_occurrence(profile_pic, '/', 6) + 1;
console.log('1. Start Pos: ' + startPos);
// Find the position of the next '.'
var stopPos = profile_pic.indexOf(".",startPos) ;
console.log('2. Stop Pos: ' + stopPos);
FB_ID = profile_pic.substring(startPos,stopPos);
console.log('profile_pic :' + profile_pic);
console.log('FB_ID :' + FB_ID);
var gender = JSON.stringify(response.gender).replace(/\"/g, "");
var name = JSON.stringify(response.first_name).replace(/\"/g, "");
console.log('name: ' + name);
console.log('** Set session variable');
client.exists("key",FB_ID, function (err, replies) {
if(!err && replies===1){
console.log("THE SESSION IS ALREADY PRESENT ");
}else{
console.log("THE SESSION DOES NOT EXIST");
// Now create a session from this
client.hmset(FB_ID, {
'gender': gender,
'name': name
});
resolve();
}});
})
.catch((err) => {
console.log(err)
reject();
});
})
} // fbUserInfo
What i get is :
1. profile_pic:https://scontent.xx.fbcdn.net/v/t1.0-1/p200x200/xxxxxxxxxx.jpg?oh=f43f7946f07e2bfb16fd0428da6a20e3&oe=5824B5F0
1. Start Pos: 48
2. Stop Pos: 96
profile_pic :https://scontent.xx.fbcdn.net/v/t1.0-1/p200x200/xxxxxxxxx.jpg?oh=f43f7946f07e2bfb16fd0428da6a20e3&oe=5824B5F0
FB_ID :13882352_10154200039865923_27612879517xxxxxxxx
name: Ethan
** Set session variable
^^^ gender :male
^^^ user_name :Ethan
THE SESSION DOES NOT EXIST
START to get client data
%%%%%%%%{}

You are not using callbacks inside promise the right way and your promise resolves before your client.hmget functions are finished.
You will need promise chain to get what you need, or you can quickly fix it like this:
return new Promise((resolve,reject) => {
client.hmget(FB_ID,'gender',function(err,reply){
if (err) {
return reject(err);
}
rowsJson.gender = reply;
console.log('^^^ gender :' + rowsJson.gender);
client.hmget(FB_ID,'name',function(err,reply){
if (err) {
return reject(err);
}
rowsJson.user_name = reply;
console.log('^^^ user_name :' + rowsJson.user_name);
resolve(rowsJson);
});
});
})

Related

TypeError: Cannot read properties of undefined (reading 'applicantid')

I am trying to make a login request (req, res functions).
I already printed out the params in server.js and it worked perfectly, but there's a problem sending it to the function in human resources.js. The params are just "undefined" once its passed on. Everything is imported and working correctly, these are just code snippets from the class. Thank you so much
Code (server.js):
app.post('/dologin', (req, res) => {
humanresources.login(req.body).then((result) => {
console.log("result", result);
res.send(result);
});
});
Code (human resources.js):
function login(req, res) {
// params: { applicantid, password }
let params = req.body;
let applicantid = params.applicantid;
let password = params.password;
client.connect(err => {
if (err) {
return "Error connecting to database";
}
collectionApplicants.findOne({_id: applicantid}, function(error, user) {
console.log('move on 2');
if (user == (undefined || null) || error) {
return res.json("An employee account couldn't be returned with the given crednetials, please try again");
} else {
comparePassword(password, user.password).then((compared) => {
if (compared != "Passwords match!") {
return res.response(compared);
} else {
// configure last signed in date to todays date & current time
var today = new Date();
var dd = String(today.getDate()).padStart(2, "0");
var mm = String(today.getMonth() + 1).padStart(2, "0"); //January is 0!
var yyyy = today.getFullYear();
today = mm + "/" + dd + "/" + yyyy;
today = new Date(today);
// update last online date
collectionApplicants.updateOne({_id: user._id}, {$set: {lastOnline: today}}, function(err, result) {
client.close();
if (err) {
return res.status(400).json("Error updating last online date");
} else {
return res.status(200).json("Successfully logged in as " + user.firstName + " " + user.lastName);
}
});
}
}).catch((error) => {
console.log(error);
return res.status(400).json("Error comparing password, please try again");
});
}
});
});
}
You are already passing req.body in your server.js , but in login function you are trying to read req.body again
Your login function can be
function login(params) {
// params: { applicantid, password }
// let params = req.body
let applicantid = params.applicantid;
let password = params.password;

Render my ejs file after my query finishes

I want to make sure that my application will only call res.render('pages/students' ...) after all my queries finishes and I get all the necessary data. However, I completely have no clue how to do this at all and I am having trouble applying all the examples I see online onto my code. Can someone give me a hand? (There are two con.query(...) in my route. I want to only render('pages/students'...) after both of these con.query completely finishes. Therefore, I am using async to run all my queries to completion. However now for some reason my page wont event load.
app.get('/admin', function(req, res) {
var sql =
'SELECT events.id, name, description, MONTHNAME(start_time) AS month, DAY(start_time) AS day, ' +
"YEAR(start_time) AS year, DATE_FORMAT(start_time, '%h:%i%p') AS start_time, HOUR(start_time) AS start_hour, MINUTE(start_time) AS start_minute, " +
"DATE_FORMAT(end_time, '%h:%i%p') AS end_time, HOUR(end_time) AS end_hour, MINUTE(end_time) AS end_minute, location, max_capacity, hidden_sign_up, " +
'eventleaders.first_name AS eventLeader FROM events LEFT JOIN eventleaders_has_events ON events.id = eventleaders_has_events.events_id ' +
'LEFT JOIN eventleaders ON eventleaders_has_events.eventleaders_id = eventleaders.id;';
var events = {};
con.query(sql, function(err, results) {
if (err) throw err;
async.forEachOf(results, function(result, key, callback) {
var date = result.month + ' ' + result.day + ', ' + result.year;
var other = 'N/A';
if (result.other !== null) {
other = result.other;
}
if (typeof events[date] === 'undefined') {
events[date] = {};
}
var studentAttendees = {};
var sql =
'SELECT * FROM students INNER JOIN students_has_events ON students.id = students_has_events.Students_id ' +
'WHERE students_has_events.Events_id = ?';
var values = [result.id];
con.query(sql, values, function(err, results1) {
if (err) throw err;
async.forEachOf(results1, function(result1, key, callback) {
studentAttendees[result1.first_name + ' ' + result1.last_name] = {
netID: result1.netID,
phoneNumber: result1.phone,
email: result1.email
};
});
//still need to get the event leader attendees
events[date][result.name] = {
startTime: result.start_time,
location: result.location,
endTime: result.end_time,
description: result.description,
eventLeader: result.eventLeader,
numberRegistered: result.hidden_sign_up,
maxCapacity: result.max_capacity,
poster: '/images/sample.jpg',
other: other,
attendees: studentAttendees
};
});
});
});
});
Two options:
app.get('/admin', function(req, res) {
...
con.query(sql, function(err, result) {
...
con.query(sql, values, function(err, result) {
events[date][currRecord.name] = {
...
};
// put it here
console.log(events);
res.render('pages/admin', {
events: events
});
});
}
});
});
Or use the Promise version of mysql
const mysql = require('mysql2/promise');
// make this async
app.get('/admin', async function(req, res) {
try {
...
// might want to move this elsewhere inside async function
const con = await mysql.createConnection({host:'localhost', user: 'root', database: 'test'});
const result1 = await con.query(sql);
// run your logic preferably inside map
// result2 is an array of Promises
const result2 = result1.map((result, index) => {
var currRecord = result[index];
var date =
currRecord.month + ' ' + currRecord.day + ', ' + currRecord.year;
var other = 'N/A';
if (currRecord.other !== null) {
console.log('here');
other = currRecord.other;
}
if (typeof events[date] === 'undefined') {
events[date] = {};
}
//get all the student attendees of this event
var studentAttendees = {};
var sql =
'SELECT * FROM students INNER JOIN students_has_events ON students.id = students_has_events.Students_id ' +
'WHERE students_has_events.Events_id = ?';
var values = [currRecord.id];
return con.query(sql)
})
// result3 is an array of results. If your results is also an array, the structure might look lik [[student], [student]] etc.
const result3 = await Promise.all(result2);
// run your logic to get events
console.log(events);
res.render('pages/admin', {
events: events
});
} catch (e) {
// handle error
console.error(e)
}
});

Variable scope; var undefined or same var loop

Meteor.methods({
'list.messages' () {
getTwilioMessages(function(err, data) {
if (err) {
console.warn("There was an error getting data from twilio", err);
return
}
data.messages.forEach(function(message) {
if (SMS.find({
sid: message.sid
}).count() > 0) {
return;
}
var image;
if (message.numMedia > 0) {
var images = [];
Meteor.wrapAsync(client.messages(message.sid).media.list(function(err, data) {
console.log(data)
if (err) throw err;
Meteor.wrapAsync(data.media_list.forEach(function(media, index) {
mediaImage = (function() {
let mediaImg = 'http://api.twilio.com/2010-04-01/Accounts/' + media.account_sid + '/Messages/' + media.parent_sid + '/Media/' + media.sid;
return mediaImg
});
}));
images.push(mediaImage());
console.log("Just One:" + mediaImage())
console.log("IMAGESSSS " + mediaImage())
}));
message.image = mediaImage();
console.log("test" + image)
} else {
message.image = null
}
if (message.from === Meteor.settings.TWILIO.FROM) {
message.type = "outgoing";
} else {
message.type = "incoming";
}
SMS.insert(message)
});
});
getTwilioMessages();
Meteor.setInterval(getTwilioMessages, 60000);
// client.calls.get(function(err, response) {
// response.calls.forEach(function(call) {
// console.log('Received call from: ' + call.from);
// console.log('Call duration (in seconds): ' + call.duration);
// });
// });
},
I expect to see different image URL's in the data.media_list.forEach. But, it returns the same image. In the console I get the desired results.
I want these results:
message.image = 'http://api.twilio.com/2010-04-01/Accounts/3039030393/Messages/303030/media/3kddkdd'
message.image = 'http://api.twilio.com/2010-04-01/Accounts/3039sdfa393/Messages/303030/media/3asdfdfsa' inserted into the correct message.
instead I get the same URl over and over resulting in the same image
for all my messages. I guess my scope is incorrect, but I have
attempted to follow: 2ality guide on scoping and Explaining
JavaScript Scope And Closures with no luck.

TypeError: Cannot read property 'toString' of undefined - why?

Here is the line (50) where this is happening:
var meetingId = meeting._id.toString(),
And here is the full, relevant code:
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var ObjectId = require('mongodb').ObjectID;
var config = require('./config'),
xlsx = require('./xlsx'),
utils = require('./utils'),
_ = require('lodash'),
url = config.DB_URL;
var meetings = [];
function findNumberOfNotesByMeeting(db, meeting, callback) {
var meetingId = meeting._id.toString(),
meetingName = meeting.name.displayValue,
attendees = meeting.attendees;
host = meeting.host;
var count = 1, pending = 0, accepted = 0;
console.log("==== Meeting: " + meetingName + '====');
_.each(attendees, function(item) {
console.log(count++ + ': ' + item.email + ' (' + item.invitationStatus + ')');
if (item.invitationStatus == 'pending') { pending++; }
else if (item.invitationStatus == 'accepted') { accepted++; }
});
console.log("*** " + attendees.length + ", " + pending + "," + accepted);
db.collection('users').findOne({'_id': new ObjectId(host)}, function(err, doc) {
var emails = [];
if (doc.emails) {
doc.emails.forEach(function(e) {
emails.push(e.email + (e.primary ? '(P)' : ''));
});
}
var email = emails.join(', ');
if (utils.toSkipEmail(email)) {
callback();
} else {
db.collection('notes').find({ 'meetingId': meetingId }).count(function(err, count) {
if (count != 0) {
console.log(meetingName + ': ' + count + ',' + attendees.length + ' (' + email + ')');
meetings.push([ meetingName, count, email, attendees.length, pending, accepted ]);
}
callback();
});
}
});
}
function findMeetings(db, meeting, callback) {
var meetingId = meeting._id.toString(),
host = meeting.host;
db.collection('users').findOne({'_id': new ObjectId(host)}, function(err, doc) {
var emails = [];
if (!err && doc && doc.emails) {
doc.emails.forEach(function(e) {
emails.push(e.email + (e.primary ? '(P)' : ''));
});
}
var email = emails.join(', ');
if (utils.toSkipEmail(email)) {
callback();
} else {
db.collection('notes').find({ 'meetingId': meetingId }).count(function(err, count) {
if (count != 0) {
var cursor = db.collection('meetings').find({
'email': {'$regex': 'agu', '$options': 'i' }
});
}
callback();
});
}
cursor.count(function(err, count) {
console.log('count: ' + count);
var cnt = 0;
cursor.each(function(err, doc) {
assert.equal(err, null);
if (doc != null) {
findNumberOfNotesByMeeting(db, doc, function() {
cnt++;
if (cnt >= count) { callback(); }
});
}
});
});
});
}
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
findMeetings(db, function() {
var newMeetings = meetings.sort(function(m1, m2) { return m2[1] - m1[1]; });
newMeetings.splice(0, 0, [ 'Meeting Name', 'Number of Notes', 'Emails' ]);
xlsx.writeXLSX(newMeetings, config.xlsxFileNameMeetings);
db.close();
});
});
As you can see, the meeting variable (which I am almost 100% sure is the problem, not the _id property) is passed in just fine as a parameter to the earlier function findNumberOfNotesByMeeting. I have found some information here on SO about the fact that my new function may be asynchronous and needs a callback, but I've attempted to do this and am not sure how to get it to work, or even if this is the right fix for my code.
You're not passing the meeting object to findMeetings, which is expecting it as a second parameter. Instead of getting the meeting object, the function receives the callback function in its place, so trying to do meeting._id is undefined.
In fact, what is the purpose of the findMeetings function? It's name indicates it can either find all meetings in the database, or all meetings with a specific id. You're calling it without a meeting id indicating you might be trying to find all meetings, but its implementation takes a meeting object. You need to clear that up first.

Change URLs into files (Parse.com using Javascript CloudCode)

I need to batch change a number of image links (URL's links that exist within a class in) to image files (that Parse.com hosts).
Cloud code is (apparently) how to do it.
I've followed the documentation here but haven't had any success.
What I wanted to do is:
Take URL link from "COLUMN_1"
Make it a file
Upload file to "COLUMN_1" (overwrite existing URL). If this is dangerous- can upload it to a new column ("COLUMN_2").
Repeat for next row
This code did not work (this is my first time with JS):
imgFile.save().then(function () {
object.set("COLUMN_1", imgFile);
return object.save();
}).then(function (CLASSNAME) {
response.success("saved object");
}, function (error) {
response.error("failed to save object");
});
Can anyone recommend how to do this?
OK- this successfully works for anyone else trying.
Parse.Cloud.job("convertFiles", function(request, status) { //Cuts the rundata out of poor runs
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
// Tell the JS cloud code to keep a log of where it's upto. Manually create one row (in class "debugclass") to get an object Id
Parse.Cloud.useMasterKey();
var Debug = Parse.Object.extend("debugclass");
var queryForDebugObj = new Parse.Query(Debug);
queryForDebugObj.equalTo("objectId", "KbwwDV2S57");
// Query for all users
// var queryForSublist = new Parse.Query(Parse.Object.extend("gentest"));
queryForDebugObj.find({
success: function(results) {
var debugObj = results[0];
var processCallback = function(res) {
var entry = res[0];
var debugObj = results[0];
debugObj.set("LastObject", entry.id);
debugObj.save();
Parse.Cloud.httpRequest({
url: entry.get("smallImage2"),
method: "GET",
success: function(httpImgFile)
{
console.log("httpImgFile: " + String(httpImgFile.buffer));
var imgFile = new Parse.File("picture.jpg", {base64: httpImgFile.buffer.toString('base64')});
imgFile.save().then(function () {
console.log("2");
entry.set("smallImage1", imgFile);
entry.save(null, {
success: function(unused) {
debugObj.increment("itemDone");
sleep(20);
res.shift();
if (res.length === 0) {
process(entry.id);
return;
}
else {
processCallback(res);
}
},
error: function(unused, error) {
response.error("failed to save entry");
}
});
});
},
error: function(httpResponse)
{
console.log("unsuccessful http request");
response.error(responseString);
}
});
};
var process = function(skip) {{
var queryForSublist = new Parse.Query("genpants");
if (skip) {
queryForSublist.greaterThan("objectId", skip);
console.error("last object retrieved:" + skip);
}
queryForSublist.ascending("objectId");
queryForSublist.find().then(function querySuccess(res) {
processCallback(res);
}, function queryFailed(reason) {
status.error("query unsuccessful, length of result " + result.length + ", error:" + error.code + " " + error.message);
});
}};
process(debugObj.get("LastObject"));
},
error: function(error) {
status.error("xxx Uh oh, something went wrong 2:" + error + " " + error.message);
}
});
});

Categories

Resources