NodeJS Can't Access Object Scope in Children [duplicate] - javascript

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 7 years ago.
I'm having some scope issues when trying to save my return data to a parent scope. Here is my source, any help would be greatly appreciated. I can not for the life of me get table to = data.
My data var console.logs correctly its just a problem of scope.
function OpenDB(mongoUrl, callBack){
var MongoClient = mongodb.MongoClient;
var url = mongoUrl || "mongodb://" + process.env.IP + "/test";
MongoClient.connect(url, function(err, db) {
if(err){
console.log(err);
}
console.log(" Connected correctly to server ");
callBack(db, function(){
console.log(" Disconnected from server ");
db.close();
});
}.bind(this));
}
var GetTableAsArray = function(tableName){
var table = [];
OpenDB(null, function(db,cb){
db.collection(tableName).find().toArray(function(err, data){
if(err){
console.log(err);
}
//this is the problem
table = data;
cb();
});
});
return table;
};

By the time GetTablesAsArray function returns, table is still just an empty array. The problem here is that your query happens in an asynchronous way, meaning that you're code doesn't wait for it to be done before proceeding. You can use a callback to execute whatever code you want with the value of tables once it is fetched.
var GetTableAsArray = function(tableName, callback){
OpenDB(null, function(db,cb){
db.collection(tableName).find().toArray(function(err, data){
if(err){
console.log(err);
}
//this is the problem
table = data;
cb();
callback (data);
});
});
};
GetTableAsArray('tableName', function (table) {
console.log(table);
});

Related

Share variable between files from module with multiple function [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 4 years ago.
I have a module.exports with multiple functions inside.
What I have understod, it is possible to share a variable to another file.
But I cannot seem to get it work.
translator.js
module.exports = {
translatorfunc: function (message, queryInput, callback) {
var parameters = {
text: queryInput
};
var parameters = {
text: queryInput,
model_id: 'es-en'
};
languageTranslator.translate(
parameters,
function (error, response) {
if (error)
bot.reply(message, 'Cannot find language that should understand this.')//console.log(error)
else
var TranslatedOutput = response.translations[0].translation;
assistant.message({
input: { 'text': TranslatedOutput }
}, function (err, response) {
if (err)
console.log('error:', err);
else
queryOutput = response.output.text[0];
var parameters = {
text: queryOutput,
model_id: 'en-es'
};
languageTranslator.translate(
parameters,
function (error, response) {
if (error)
bot.reply(message, 'Cannot find language that should understand this.')//console.log(error)
else
TranslatedOutput = response.translations[0].translation;
}
)
});
}
)
}
}
The variable I'm trying to send to a different file is TranslatedOutput
I also tried to wrap the function languageTranslator.translate as a function, but when I'm calling the variable, it says undefined.
And to get the variable
var translator = require('./tools/translator')
console.log(translator.translatorfunc.TranslatedOutput);
You have to make your variable an attribute of the module.exports object:
module.exports.TranslatedOutput = 'something';
This way you can import it like that:
var TranslatedOutput = require('myModule'). TranslatedOutput;

Bringing one value outside of an err response [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 4 years ago.
I am trying to get one of the events outside and print it. Of course the 'answer' variable scope is only inside.
As you can see, this one gets a list of all the events stored on a specific calendar. I am able to access specific events from the array. However. I don't know how to get that one value out of this.
I am not that familiar with coding, help appreciated.
//my question is just above the last line.
let google = require('googleapis');
let privatekey = mypk.json;
// configure a JWT auth client
let jwtClient = new google.auth.JWT(
privatekey.client_email,
null,
privatekey.private_key,
['https://www.googleapis.com/auth/calendar']);
//authenticate request
jwtClient.authorize(function (err, tokens) {
if (err) {
console.log(err);
return;
} else {
console.log("Successfully connected!");
}
});
let calendar = google.calendar('v3');
calendar.events.list({
auth: jwtClient,
calendarId: 'xxxxx#group.calendar.google.com'
}
, function (err, response, cb) {
if (err) {
console.log('The API returned an error: ' + err);
return;
}
var events = response.items;
var singleEvent = events[0].summary;
return;
/* if (events.length == 0) {
console.log('No events found.');
} else {
console.log('Event from Google Calendar:');
for (let event of response.items) {
console.log('Event name: %s, Creator name: %s, Create date: %s', event.summary, event.creator.displayName, event.start.date);
}
}*/
}
);
//this is what I need to get, one event but the variable has no scope here.
console.log ('this is the ' + singleEvent);
Declare the variable singleEvent just after calendar
Like this:
let calendar = google.calendar('v3');
let singleEvent;
And inside the callback do the following:
singleEvent = events[0].summary;
Note: Understanding scopes in Javascript is probably the most important thing you need to learn. This article will probably help you a lot:
https://scotch.io/tutorials/understanding-scope-in-javascript

How to return a boolean if a query search has elements? [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
I have a client sending JSON information to the server and trying to make a register. JSON includes name and password of this user. Before the server makes the register into the database it needs to make sure that the username is available. For this purpose i created a function called isRegisted(req) that makes a search on the database and if the result.length is greater than zero then set a boolean value to true and at the end of the function returns this boolean value.
The mysql search returns what it's expected in "result" but at the end the boolean value is not set and the console.log prints undefined.
Here's my code:
function register(req , res){
res.setHeader('Content-Type', 'application/json');
console.log(isRegisted(req));
}
function isRegisted(req){
var flag;
var query = conn.query("SELECT * FROM Users WHERE name=?", [ req.body.name ], function(err, result) {
if(err){
console.error(err);
return;
}
console.log(result);
if(result.length > 0)
flag = true;
else
flag = false;
});
return flag;
}
Thank you for your attention.
The problem with your code is, that you make an asynchronious request to the database. The function(err,result) will only be executed AFTER the query was done in your database. So you cannot be sure, when the function(err,result) will be called. So in mostly every case the flag is always undefined, because the database has not executed the query, which results in an undefined variable flag. The circumvent this problem, do your additional logic in the function(err, result) .
In this case, you have a async. function, so parent function doesn't wait for child function execution and returns undefined. Something like this may be useful for you:
var successFn = function() {console.log('success');},
errorFn = function() {console.log('error');};
function register(req , res){
res.setHeader('Content-Type', 'application/json');
console.log(isRegisted(req, successFn, errorFn));
}
function isRegisted(req, successFn, errorFn){
var flag;
var query = conn.query("SELECT * FROM Users WHERE name=?", [ req.body.name ], function(err, result) {
if(err){
errorFn();
}
if(result.length > 0) {
successFn();
}
});
}

Mongoose does not send the updated result [duplicate]

This question already has answers here:
Mongoose findByIdAndUpdate not returning correct model
(2 answers)
Closed 7 years ago.
Im trying to add an item to an array and get back the updated model.
I PUT my request like so:
addCarToDriver(CarToAdd) {
const self = this;
request
.put('api/drivers/' + this.state.race._id)
.send({
car: CarToAdd})
.end(function(err, res) {
console.log(res.body);
self.setState({race: res.body});
});
}
It hits the server here :
MyRace.findByIdAndUpdate(
req.params.myrace_id,
{ $push: { 'cars': req.body.car } },
function(er, model) {
if (er) {
console.log(err);
return res.send(err);
}
console.log(model);
return res.json(model);
});
Now in the request callback I would expect the new updated model to get logged, i.e with the new Car. It does not. The "old" version gets logged. However, if i refresh the page the model gets updated with the new car.
Of course I need to setState directly in the callback. Any tips on how to do this?
Mongoose 4 has changed .findAndUpdate behavior to return the old document by default, and if you want the new updated one you need to pass {new:true}, because that was the actual behavior in MongoDB
You can patch the Query to set options.new=true to have the old way back:
var __setOptions = mongoose.Query.prototype.setOptions;
mongoose.Query.prototype.setOptions = function(options, overwrite) {
__setOptions.apply(this, arguments);
this.options['new'] = true;
return this;
};

Functions are still being called asynchronously. What am I doing wrong?

My code is supposed to download 5 files exported from our school's database, then run a query based on the first export (there will be queries for the other four files, and there are three schools, so my functions need to be scalable).
I have a function called "download" and another function called "updateSchedule." Both of these functions work separately.
var download = function(file){
var deferred = q.defer();
var i = 1;
var ftpGet = function(){
var number = i++;
toString(number);
filename = file+number+'.csv';
ftp.get(filename, filename, function(hadErr){
if (hadErr){
console.error('There was an error retrieving ' + filename);
}else{
console.log(filename + ' downloaded');
if(i <= 5){
ftpGet();
}else{
deferred.resolve();
}
}
});
}
ftpGet();
return deferred.promise;
}
var updateSchedule = function(school, school_id){
var deferred = q.defer();
console.log('');
connectionpool.getConnection(function(err, connection){
if(err){
console.error('CONNECTION error: ', err);
}else{
connection.query('DELETE FROM schedule WHERE school_id = "'+school_id+'"', function(err, rows){
if (err) console.error(err);
var path = './'+school+'_export1.csv';
var reader = csv.createCsvFileReader(path, {'separator': ',','quote': '"','excape': '"','comment': ''});
reader.addListener('data',function(data){
connection.query('INSERT INTO schedule SET section_id = "'+data[0]+'", student_id = "'+data[1]+'", course_number = "'+data[2]+'", period = "'+data[3]+'", teacher_id = "'+data[4]+'", school_id = "'+school_id+'"', function(err, rows){
if (err) console.error(err);
deferred.resolve();
});
});
});
connection.release();
console.log(school+' schedule updating...');
}
});
return deferred.promise;
}
When I call them using promises, however, I get an error saying it can't open the file. What am I doing wrong?
download('lca_export').then(updateSchedule('lca', '517'));
Change this:
download('lca_export').then(updateSchedule('lca', '517'));
to this:
download('lca_export').then(function() {
updateSchedule('lca', '517');
});
You were calling updateSchedule() immediately and passing the result to .then() rather than passing a function reference to .then() that can be called later. Thus, updateSchedule() was running before download() had done its work. This is a very common mistake. Just remember that if there are parens after the function name it will execute immediately. If it's just a function name or an anonymous declaration without parens, then you're passing a function reference.
Some other things to cleanup:
Add var in front of filename to make it a local variable rather than an implicit global.
Remove the toString(number). At best it isn't needed at all and isn't doing anything since you aren't assigning the result to anything. At worst, it's causing an error because there is no function toString(). FYI, numbers are automatically converted to strings when added to a string so you do not need to do that manually.

Categories