Nodejs - Why my variable in class is undefined? - node.js

In crawler.js :
var async = require('async');
var request = require('request');
var cheerio = require('cheerio');
var Helper = require('./helper.js');
var helper = new Helper();
var Crawler = function(){
var me = this;
this.listCategory;
this.getCategory = function(){
//1. not use async : test key input is idMenu
helper.categoryInMenu(1, function(err, result){
me.listCategory = result;
});
//2. use async : test key input is idMenu
async.map([1], helper.categoryInMenu, function(err, result){
me.listCategory = result;
//console.log(result);
});
console.log(me.listCategory); // return undefined
}
}
module.exports = Crawler;
When i set me.listCategory = result; (with result != null) then call listCategory in file main.js or console.log it in file crawler.js.
Display in command is undefined.
File main.js
var Crawler = require('./crawler.js');
var snipper = new Crawler();
snipper.getCategory();
console.log(snipper.listCategory);
I try use async module with function map, it not work.
Maybe, i not set me.listCategory = return of function helper.categoryInMenu.
File helper.js
var db = require('mysql');
var config = require('./configLoader.js');
config.load(__dirname+'/config.json');
var Helper = function(){
var me = this;
this.conn = db.createConnection(config.get('db'));
this.menu = function(callback){
me.conn.query("SELECT * FROM `menu`", function(err, rows){
callback(err, rows);
});
}
// return list category with "input" is a idMenu
this.categoryInMenu = function(idMenu, callback){
me.conn.query("SELECT * FROM `category` WHERE idMenu = ?", idMenu, function(err, rows){
callback(err, rows);
});
}
// return config of Category with "input" is a idCategory (Category)
this.dom = function(idCategory, callback){
me.conn.query("SELECT * FROM `category` WHERE id = ?", idCategory, function(err, rows){
callback(err, JSON.parse(rows[0].dom));
});
}
}
module.exports = Helper;

Map in all languages is used to transform the values of iterable into something else, that is why you should return in the callback function and the result will be new array containing only the returned values. If you need to iterate only, you should use arr.forEach (>ES5) or simple for loop.
Your problem is that async.map is asynchronous which means console.log(me.listCategory); is executed before the actual map.
Array.map is actually ES5 standard so you don't need async module to map arrays, also the native map is synchronous.

Related

Check function name exists and call by String

I am trying to facilitate and organize my work between socket communication and Node.JS (My project is too big)
Instead of socket.emit() function in client-side I use a function that I created:
function socketEmit(socketName, functionName, data){
socket.emit(socketName, {functionName: functionName, data: data});
}
socketEmit('exampleClass', 'exampleFunction', 'test');
socketEmit('exampleClass2', 'exampleFunction2', 'test');
After emit, I get the socket (socket.on) on the server-side with this function. And register it in the class depending on the "socketName"
socket.on('exampleClass', function (socketData){
var exampleClass = require('./server/exampleClass.js');
exampleClass.registerSocket(socket, socketData);
})
socket.on('exampleClass2', function (socketData){
var exampleClass2 = require('./server/exampleClass2.js');
exampleClass2.registerSocket(socket, socketData);
})
Within the classes has this function "registerSocket" to perform the same
exampleClass.js
module.exports = {
registerSocket: function(socket, socketData){
var functionName = socketData.functionName;
var data = socketData.data;
[functionName](socket, data);
},
}
function exampleFunction(socket, data){
console.log('test');
}
However, I have an error in this part in registerSocket function:
[functionName] is not a function
You're trying to call a an array [functionName](socket, data);:
const array = [functionName]; // array
array(socket, data); // you can't :)
Put the functions in an object, and access it using [] notation.
const fns = {
exampleFunction(socket, data){
console.log('test');
}
};
module.exports = {
registerSocket: function(socket, socketData){
var functionName = socketData.functionName;
var data = socketData.data;
fns[functionName](socket, data);
},
}

How to return result values from node_redis function

I need to return the replies from this function and use the replies in other function. I am newbie to NodeJs and trying to figure out a simple solution.
var getKeys = function(key){
var addkey = key + '*'
myClient.keys(addkey, function (err, replies) {
console.log(replies);
});
}
Question 2:
Is there a way to take variable inside the node_redis function?
Example:
redis_get -> Defined function for getting values
thingsUUID[i] = thingsUUIDKey[i].split("_").pop()
redis_get("key", function(redis_items) {
console.log(thingsUUID[i]);
});
Inside redis_get thingsUUID is undefined. I want to concatenate the thingsUUID and the result redis_items
you could add the callback that is used in the myClient.keys function to your getKeys function like this:
var getKeys = function(key, callback){
var addkey = key + '*'
myClient.keys(addkey, callback);
}
getKeys("EXAMPLE_KEY", function (err, replies) {
if (err) console.error(err);
console.log(replies);
});
As myClient.keys requires a callback it is async and you can't return the response of this back into a value.
This is a good resource to get an overview about how callbacks work:
https://github.com/maxogden/art-of-node#callbacks
I'm not quite sure what you want to do, but if your variable thinksUUID is defined outside redis_get it should be accessible inside the callback:
var thinksUUID = [1,2,3,4];
var getKeys = function(key, callback){
var addkey = key + '*'
myClient.keys(addkey, callback);
}
getKeys("EXAMPLE_KEY", function (err, replies) {
if (err) console.error(err);
replies.forEach(function(item, index){
console.log(item);
console.log(thinksUUID[index]);
});
});
If you want to hand over the variable thinksUUID to your defined function redis_get you need to change your signature of redis_get(key, callback) to redis_get(key, thinksUUID, callback)
// using Node.js >= v8 built-in utility
const { promisify } = require('util');
// forcing function to return promise
const getAsync = promisify(redisClient.get).bind(redisClient);
const value = await getAsync(key);
console.log('value of redis key', value)

Putting MongoDB queries, inserts and removes in module.exports or exports

Is there a way to put MongoJS/Mongoose queries, inserts and removes in module.exports while getting an confirmation object back?
server.js
var mongoq = require('./models/mongoq.js');
var result = mongoq.connectToServer();
console.log(result);
mongoq.js
var mongojs = require('mongojs');
db = mongojs('config', ['questions']);
module.exports = {
//var answer;
connectToServer: function(){
db.questions.find(function (err, docs) {
return docs;
}
//return answer;
};
The result variable returns undefined, and if I put the return outside of a query, it wants to send it before doing the query.
Is there a way that I can force the module.exports to wait for the query before returning it?
Thank you
You can achieve this by my making use of a callback. I.e. you call the module from the other file with a function as parameter, this function has the result variable as parameter. This function will be executed when the query has completed.
server.js
var mongoq = require('./models/mongoq.js');
mongoq.connectToServer(function(result) {
console.log(result);
});
mongoq.js
var mongojs = require('mongojs');
db = mongojs('config', ['questions']);
module.exports = {
connectToServer: function(callback) {
db.questions.find(function (err, docs) {
callback(docs);
});
}
};

Send parameters between promises

Im doing a asynchronous process with node.js. using promises. My code is like this:
var net = require('net');
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database('MyBBDD.db');
var net = require('net');
var Q = require("q");
var firstFunction = function(v_user, v_mystring){
var deferred = Q.defer();
var mi;
stmt = db.prepare("SELECT text1 FROM my_table WHERE user = ?");
stmt.bind (v_user);
stmt.get(function(error,row){
if(!error && row){
deferred.resolve({string: v_mystring, query: row.text1});
}
deferred.reject(new Error(error));
});
return deferred.promise;
};
var secondFunction = function(result){
console.log(result.string);
console.log(result.query);
};
firstFunction('user000','Hello').then(secondFunction);
All in my code work fine but now, I want to concatenate in secondFunction my string received from firstFunction with other string for example "MyNewString".
Somebody know how can I solve it? Can I send "MyNewString" from my firstFunction to my secondFunction?
Thanks in advance.
Best regards.
The best to solve it will be resolve promise with object. Instead of returning just one value - result of querying DB you can return object that covers needed value.
With bind:
function firstFunction(string) {
return Promise.resolve({string: string, query: 'some result of query'})
}
function secondFunction(otherText, result) {
console.log(result.query) // you have still access to result of query
return result.string + otherText
};
firstFunction('foo').then(secondFunction.bind(null, 'bar')).then(console.log);
With closure
function firstFunction(string) {
return Promise.resolve({string: string, query: 'some result of query'})
}
function secondFunction(text) {
return function(result) {
return result.string + text
}
};
firstFunction('foo').then(secondFunction('bar')).then(console.log);
With anonymous function expression
function firstFunction(string) {
return Promise.resolve({string: string, query: 'some result'})
}
function secondFunction(text, otherText) {
return text.string + otherText
};
firstFunction('foo').then(function(result) {
return secondFunction(result, 'bar')
}).then(console.log);

nodejs get sqlite3 query result using promise or wait

This is my first personal project in Nodejs. I'm trying to get in live soon.
I have a Nodejs server that uses sqlite3. There are only 3000 rows with word, transform and a precalculated value each in a column of the table, which is already populated.
I need to just lookup the word in the DB to be sure it is valid.
var sqlite3 = require("sqlite3").verbose();
var db = new sqlite3.Database("validate.db");
db.get("SELECT * FROM tab WHERE w = ?", word, function(err, row) {
if(err) { console.log("Lookup:",word,", Error => ",err); return false; }
return true;
});
The problem is that the caller of this code has a lot of context and need the operation to wait. So, I tried this
function dbLookup(db, w) {
return function(cb) {
var rows = [];
db.exec('SELECT w FROM tab WHERE w = "'+w+'"')
.on('row', function(r) {
rows.push(r)
})
.on('result', function() {
cb(rows);
});
}
async.each([word], function(w) {
dbLookup(this.db, w);
}, function(err) {
if(err) {console.log("...ERROR..."); return false; }
else {console.log("...SUCCESS..."); return true; }
});
This doesn't solve the wait issue as the callback can fire at its own pace.
I read that promise using something like bluebird can solve my problem
but now I'm not able to get the value/result of the query out:
I've been pulling my hair for so long. Please help me either get the async working or get the result back from the promise approach.
var async = require('async');
var sqlite3 = require("sqlite3").verbose();
var db = new sqlite3.Database("validate.db");
function check(word, callback) {
db.get("SELECT count(1) cnt FROM tab WHERE w = ?", word, callback)
}
async.map(words, check, function(err, results) {
if (err)
return console.log('Query error')
var all_checked = results.filter(function(r) {
return r.cnt > 0
});
...
});
Or
var sqlite3 = require("sqlite3").verbose();
var db = new sqlite3.Database("validate.db");
db.all("SELECT distinct w FROM tab", function(err, rows) {
var all_checked = words.filter(function (w) {
return rows.indexOf(w) != -1;
})
...
})

Resources