how to use inner's result in outer function in node.js - javascript

currently,i learn node-mysql in node.js,but I meet a question,try a lot,i don't how to solve it ?
like this:
var express = require('express');
var app = express();
var mysqlcon=require('./testmysql');
var mysqlconn=mysqlcon.conn;
var http=require("http");
var url=require("url");
app.use('/sql',testExist).listen(3000);
function testExist(req,res,next){
var query = url.parse(req.url,true).query;
var name=query.name;
mysqlconn.connect();
var result=function(err, results){
return results.length;
}
mysqlconn.query('select * from user where name = ?',[name],result);
mysqlconn.end();
if(result>1)
console.log('result:'+result)
res.end("name is already exist!")
}
I want to get the inner function's result in outer function ,for example the length of such query will be 1(results.length==1),but i want to use the result in testExist(),we know that node use callback function,so that i can't get the inner result in outer function. So can any guys help me to solve it.

you need move the using code inside the callback.
function callback(err, results) {
if(results.length >1) console.log('result:' + results.length);
res.end("name is already exists!");
}
mysqlconn.query("select * from user where name= ?", [name], callback);

Related

Save into a variable the result from an async function

How can I save the result of an async function into a variable so I can use it below?
The code looks like this:
app.post('/reg', function(request, response){
var user = request.body.username;
var pass = request.body.password;
var quest = request.body.question;
var ans = request.body.answer;
MongoClient.connect(uri, function(err, db) {
var dbc = db.db("chat");
dbc.collection("accounts").find({username: `${user}`}).toArray(async (err, result) => {
console.log(result.length)
const a = await result.length;
return a;
});
console.log(a); <--------- here i got the error: a is not defined
if(a==1){
response.send("already_exist");
}
else{
response.send("succes");
obj={username: user, password: pass, question: quest, answer: ans};
var dbc = db.db("chat");
dbc.collection("accounts").insertOne(obj);
}
db.close();
// response.send("yep");
});
});
I have tried a lot of options but i cant find anything useful.
The thing that I want to do here is finding if an username already exists in database, if you have another ideas please tell me.
the variable a is not in scope of the main function, try declaring it outside at main/global level.
Also you're returning the value from the function, just use it.
const results = dbc.collection("accounts").find({..

Javascript function doesn't return query result

I am trying to figure out why one of my queries won't return the value from a query...my code looks like this:
var client = new pg.Client(conString);
client.connect();
var query = client.query("SELECT count(*) as count FROM sat_scores")
// Don't use demo key in production. Get a key from https://api.nasa.gov/index.html#apply-for-an-api-key
function getNEO(callback) {
var data = '';
query.on('rows', function(rows) {
console.log("Row count is: %s", rows[0].count)
data += rows[0].count;
});
query.on('end', function() {
callback(data);
});
}
with that, getNEO returns a blank...but if I set var data = '4', then getNEO returns 4....the query should return 128 but it just returns a blank...
First of all, getNEO() doesn't return anything - I'm operating on the assumption that you call getNEO() exactly once for your query, and pass in a callback to handle the data, and that callback is what's not getting the appropriate data?
My typical recommendation for troubleshooting things like this is to simplify your code, and try and get really close to any example code given (for instance):
var client = new pg.Client(conString);
// define your callback here, in theory
client.connect(function (err) {
if (err) throw err;
var query = client.query("SELECT count(*) as count FROM sat_scores"),
function(err, result) {
if (err) throw err;
console.log(result.rows.length);
}
);
});
... I'm doing a couple things here you'll want to note:
It looks like the client.connect() method is asynchronous - you can't just connect and then go run your query, you have to wait until the connection is completed, hence the callback. Looking through the code, it looks like it may emit a connect event when it's ready to send queries, so you don't have to use a callback on the connect() method directly.
I don't see a data event in the documentation for the query object nor do I see one in the code. You could use the row event, or you could use a callback directly on the query as in the example on the main page - that's what I've done here in the interest of simplicity.
I don't see the count property you're using, and row[0] is only going to be the first result - I think you want the length property on the whole rows array if you're looking for the number of rows returned.
I don't know if you have a good reason to use the getNEO() function as opposed to putting the code directly in procedurally, but I think you can get a closer approximation of what you're after like this:
var client = new pg.Client(conString);
// define your callback here, in theory
client.connect();
function getNEO(callback) {
client.on('connect', function () {
var query = client.query("SELECT count(*) as count FROM sat_scores"));
query.on('end', function(result) {
callback(result.rowCount);
});
});
}
... so, you can call your getNEO() function whenever you like, it'll appropriately wait for the connection to be completed, and then you can skip tracking each row as it comes; the end event receives the result object which will give you all the rows and the row count to do with what you wish.
so here is how I was able to resolve the issue....I moved the var query inside of the function
function getNEO(state, callback) {
var conString = "postgres://alexa:al#alexadb2.cgh3p2.us-east-1.redshift.amazonaws.com:5439/alexa";
var client = new pg.Client(conString);
client.connect();
var data = '';
var query = client.query("SELECT avg(Math) as math, avg(Reading) as reading FROM sat_scores WHERE State = '" + state + "'");
console.log("query is: %s", query);
query.on('row', function(row) {
console.log("Row cnt is: %s", row.math);
console.log("row is: " + row)
data += row;
});
console.log("made it");
query.on('end', function() {
callback(data);
});
}

Variable within for loop giving max value

EDIT: Updated with full code.
I'm writing javascript code in node.js that is meant to loop through an array of data that I have scraped from the web. The purpose of the code is to:
1) Check the player table to see if that player's name exists in a record, and
2) If that player doesn't exist, add him to the database.
Here is my code:
var cheerio = require('cheerio');
var request = require('request');
var data = [];
var mysql = require('mysql');
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'blahblah',
database: 'test',
port: 3306 });
connection.connect();
request('http://www.basketball-reference.com/friv/dailyleaders.cgi?month=12&day=28&year=2014', function(err, response, body){
if(!err && response.statusCode ==200){
var $ = cheerio.load(body);
$('td', 'tbody').each(function(){
var url = $(this).attr('href');
var text = $(this).text();
data.push(text);
});
for(i=1;i<data.length;i+=26){
var query = connection.query(
"SELECT * FROM player WHERE name = '"+data[i]+"'",function(err, result, fields) {
if (err) throw err;
if(result.length==0){
//var insertQuery = "INSERT INTO player (provider_id, team_id, position_id, name) VALUES (1, (SELECT id FROM team WHERE slug = '"+data[i+1]+"'),1,'"+data[i]+"');";
console.log(i);
}
});
}
}
});
Note that I commented out my INSERT query for testing purposes, but the player name is located in data[i] while the team name is in data[i+1].
To test, I am just printing i to the console, and every loop it prints out the max value of i, which is 3225. However, that console.log command is INSIDE the for loop, so shouldn't it print each value of i as it is incremented?
This is similar to this question: JavaScript closure inside loops – simple practical example
That answer explains the why things are acting the way they are.
This happens in closures, if you are referencing a variable in a callback and that variable was already at that max value before the callback was executed.
Here's an example of what your code is doing (bad with callbacks):
function a(){
var i = 0;
var callbacks = [];
for (i=0;i<100;i+=25){
callbacks.push(function(){
alert(i);
});
}
return callbacks;
}
var callbackArray = a();
for( f in callbackArray){
callbackArray[f]();
}
Here's what it should be doing:
function createFunction(i){
return function(){
alert(i);
}
}
function a(){
var i = 0;
var callbacks = [];
for (i=0;i<100;i+=25){
callbacks.push(createFunction(i));
}
return callbacks;
}
var callbackArray = a();
for( f in callbackArray){
callbackArray[f]();
}
For your fix, you should do something like this:
// outside of the code you posted, as a separate function.
function createPlayerSelectionCallback(data,i){
return function(err, result, fields) {
if (err) throw err;
if(result.length==0){
//var insertQuery = "INSERT INTO player (provider_id, team_id, position_id, name) VALUES (1, (SELECT id FROM team WHERE slug = '"+data[i+1]+"'),1,'"+data[i]+"');";
console.log(i);
}
}
}
// this for loop stays in the same place, just modified to use the new function.
for(i=1;i<data.length;i+=26){
var query = connection.query(
"SELECT * FROM player WHERE name = '"+data[i]+"'",createPlayerSelectionCallback(data, i))
}

Node.js & Node-Postgres: Putting Queries into Models

I would like to 'functionalize' my queries by putting them into functions which have apt names for the task.
I want to avoid putting everything in the req, res functions (my controllers), and instead put them in 'models' of sorts, that is, another JavaScript file that will be imported and used to run the functions that execute queries and return the results on behalf of the controller.
Assuming that I have the following setup for the queries:
UserController.js
exports.userAccount = function(req, res, next) {
var queryText = "\
SELECT *\
FROM users\
WHERE id = $1\
";
var queryValues = [168];
pg.connect(secrets.DATABASE_URL, function(err, client, done) {
client.query(queryText, queryValues, function(err, result) {
res.render('pathToSome/page', {
queryResult: result.rows
});
});
});
}
Here, while I'm in the query, I essentially redirect and render a page with the data. That works fine. But I want to take out all that pg.connect and client.query code and move it to a separate file to be imported as a model. I've come up with the following:
UserModel.js
exports.findUser = function(id) {
// The user to be returned from the query
// Local scope to 'findUser' function?
var user = {};
var queryText = "\
SELECT *\
FROM users\
WHERE id = $1\
";
var queryValues = [id];
pg.connect(secrets.DATABASE_URL, function(err, client, done) {
client.query(queryText, queryValues, function(err, result) {
// There is only ever 1 row returned, so get the first one in the array
// Apparently this is local scope to 'client.query'?
// I want this to overwrite the user variable declared at the top of the function
user = result.rows;
// Console output correct; I have my one user
console.log("User data: " + JSON.stringify(user));
});
});
// I expect this to be correct. User is empty, because it was not really
// assigned in the user = result.rows call above.
console.log("User outside of 'pg.connect': " + JSON.stringify(user));
// I would like to return the user here, but it's empty!
return user;
};
and I'm calling my model function as so:
var user = UserModel.findUser(req.user.id);
The query executes perfectly fine in this fashion - except that the user object is not being assigned correctly (I'm assuming a scope issue), and I can't figure it out.
The goal is to be able to call a function (like the one above) from the controller, have the model execute the query and return the result to the controller.
Am I missing something blatantly obvious here?
pgconnect is an asynchronous call. Instead of waiting for data to return from the database before proceeding with the next line, it goes ahead with the rest of the program before Postgres answers. So in the code above, findUser returns a variable that has not yet been populated.
In order to make it work correctly, you have to add a callback to the findUser function. (I told you wrong in a previous edit: The done parameter in pg.connect is called in order to release the connection back to the connection pool.) The final result should look something like this:
exports.findUser = function(id, callback) {
var user = {};
var queryText = "SELECT FROM users WHERE id = $1";
var queryValues = [id];
pg.connect(secrets.DATABASE_URL, function(err, client, done) {
client.query(queryText, queryValues, function(err, result) {
user = result.rows;
done(); // Releases the connection back to the connection pool
callback(err, user);
});
});
return user;
};
And you'd use it, not like this:
var user = myModule.findUser(id);
But like this:
myModule.findUser(id, function(err, user){
// do something with the user.
});
If you have several steps to perform, each of them dependent on data from a previous asynchronous call, you'll wind up with confusing, Inception-style nested callbacks. Several asynchronous libraries exist to help you with making such code more readable, but the most popular is npm's async module.

How to get a return value from asynchronous function in Node.js? [duplicate]

This question already has an answer here:
Why do I get an empty object when a function is invoked in node.js?
(1 answer)
Closed 8 years ago.
I want to get a return-value from this asynchronous function exports.getServices. But I just get nothing / null back.
var http = require("http");
var mysql = require('mysql');
var url = require("url");
var connection = mysql.createConnection({
...
});
connection.connect();
exports.getServices = function (){
connection.query('SELECT DISTINCT SERVICE FROM booking_count', function(err, rows, fields) {
if (err) throw err;
var services = new Array();
for (var i in rows) {
services[i] = rows[i].SERVICE;
}
return services;
});
}
I access this method from another module:
var express = require('express');
var hbs = require('express3-handlebars');
var app = express();
app.engine('html', hbs({defaultLayout: 'layout'}));
app.set('view engine', 'html');
app.set('views', __dirname + '\\views');
app.use(express.bodyParser());
var mysql = require('./mysql');
app.get('/', function(req, res) {
res.render('index',{title:"Services", services:mysql.getServices()});
});
app.get('/article/:id', function(req, res) {
var entry = blogEngine.getBlogEntry(req.params.id);
res.render('article',{title:entry.title, blog:entry});
});
app.listen(3000);
It would be very helpful if you could post a corrected code. Thank you very much in advance!
You don't provide any information about what module implements connection. Also, you don't make totally clear which function [getServices(), or the callback function passed to query()] is not returning anything. However, I will still try to answer your question.
The getServices() function never returns anything -- it just calls query(). So, obviously, you can't expect to get a result like this:
var result = getServices(...);
The callback function does return a value, but since it is the query() function that is calling it, there is no way for you to get that return value. Also, query() is probably ignoring any return value, anyway.
To fix this, you need to pass to getServices() your own callback function to receive the results. So, your implementation should look more like this:
connection.connect();
exports.getServices = function (next) {
connection.query('SELECT DISTINCT SERVICE FROM booking_count', function(err, rows, fields) {
if (err) throw err;
var services = new Array();
for (var i in rows) {
services[i] = rows[i].SERVICE;
}
next(services);
});
}
However, you should figure out if throwing an error (in the original callback, when there is an error) will cause problems (like causing your server to crash). You may want to do something else instead:
connection.connect();
exports.getServices = function (next) {
connection.query('SELECT DISTINCT SERVICE FROM booking_count', function(err, rows, fields) {
if (err) return next(err); // Pass err to next, and immediately return.
var services = new Array();
for (var i in rows) {
services[i] = rows[i].SERVICE;
}
next(null, services); // Pass result to next (with no error).
});
}
Welcome to the world of asynchronous functional programming!

Categories

Resources