How to get response from callback every time api called? - javascript

I have search function that receive string from client, so once loop process is done sending matching results to client using callback. With below code two issues
1-first time when i have search string it sends the response results but when
2- second if i search different string it sends empty array of results
3- if i search first string again i get the response
Any idea what is implemented wrong in below code.
app.js
app.get('/serverSearch', function (req, res) {
var searchTxt = req.query.searchTxt;
dirDirectory.readDirectory(function(logFiles){
// res.json(logFiles);
if(logFiles){
searchFileService.readFile(searchTxt,logFiles,function(lines,err){
console.log('Logs',lines);
if (err)
return res.send();
res.json(lines);
})
}
});
console.log('Search text', searchTxt);
});
searchService.js
var results = [];
var searchStr;
function readFile(str, logFiles, callback) {
searchStr = str;
// loop through each file
async.eachSeries(logFiles, function (logfile, done) {
// read file
fs.readFile('logs/dit/' + logfile.filename, 'utf8', function (err, data) {
if (err) {
return done(err);
}
var lines = data.split('\n'); // get the lines
lines.forEach(function(line) { // for each line in lines
if (line.indexOf(searchStr) != -1) { // if the line contain the searchSt
results.push(line);
}
});
// when you are done reading the file
done();
});
// wrong: }), function (err) {
}, function (err) {
if (err) {
console.log('error', err);
}
console.log('all done: ', results);
// wrong: results.map(result, function (result){
results.map(function (result){
console.log(result);
});
// send back results
callback(results);
results = [];
});
}

Related

return array from tedious

Can't return an array. At the exit you need to get each value separately to insert into the database. Maybe somewhere I made a mistake with the callback. Code below.
function executeTest(connection, callback) {
var results = [];
var request = new Request(ted_select, function(error) {
if (error) {
return callback(error);
}
// pass the results array on through the callback
callback(null, results);
});
request.on("row", function(rowObject) {
// populate the results array
results.push(rowObject);
});
connection.execSql(request);
}
function test(callback) {
var connection = new Connection(config);
connection.on('connect', function(err) {
if (err) {
console.log(err);
} else {
console.log('Connect database');
executeTest(connection, function(error, results) {
// here is the results array from the first query
console.log(results);
});
setTimeout(function(){connection.close(console.log('Disconnect database'));},10000);
}
callback(null, results);
});
}
var value = test();
console.log(value);
Thanks.

how to return array in Node.js from module

getting undefined all the time "main.js":
var dbAccess = require('../dao/dbAccess');
dbaInstance = new dbAccess();
var wordPool = dbaInstance.getWordPool();
console.log (wordPool);
and "dbAccess.js" contains:
var DatabaseAccess = function() {}
DatabaseAccess.prototype.getWordPool = function () {
RoundWord.find({},'words decoys', function(err, wordPoolFromDB) {
if (err) throw err;
//console.log(wordPoolFromDB); -working ok
return (wordPoolFromDB);
});
}
module.exports = DatabaseAccess;
why is it not working?
DatabaseAccess.prototype.getWordPool is not returning any result.
Since you are using an asynchronous function, you need do one of these things:
a) Take a callback as parameter and invoke the callback with a result
DatabaseAccess.prototype.getWordPool = function (cb) {
RoundWord.find({}, 'words decoys', function(err, results) {
if (err) {
return cb(err, null);
}
cb(null, results);
});
}
The callback convention is: cb(error, results...)
b) Use promises
DatabaseAccess.prototype.getWordPool = function () {
return RoundWord.find({}, 'words decoys', function (err, results) {
if (err) {
throw err; // however you might want to sanitize it
}
return results;
});
}
To consume this result you will need to do it as a promise
databaseAccess.getWordPool()
.catch(function (err) {
// process the error here
})
.then(function (results) {
// something with results
});
It will work if you change to this:
var dbAccess = require('../dao/dbAccess');
dbaInstance = new dbAccess();
dbaInstance.getWordPool(function(wordPool){console.log (wordPool);});
And:
var DatabaseAccess = function() {}
DatabaseAccess.prototype.getWordPool = function (cb) {
RoundWord.find({},'words decoys', function(err, wordPoolFromDB) {
if (err) throw err;
//console.log(wordPoolFromDB); -working ok
cb(wordPoolFromDB);
});
}
module.exports = DatabaseAccess;
If the function is Asynchronous you need to pass a callback to find to get the result:
DatabaseAccess.prototype.getWordPool = function (callback) {
RoundWord.find({},'words decoys', function(err, wordPoolFromDB) {
if (err) throw err;
callback(err, wordPoolFromDB);
});
}
and call it as follows in main:
dbaInstance.getWordPool(function (err, wordPool) {
console.log (wordPool);
// wordPool is only available inside this scope,
//unless assigned to another external variable
});
// cannot access wordPool here

Async double callback in NodeJS loop

I'm going to the next step of my webscraper today !
I'm already looping on an url array with async and I would loop again in this callback and wait for its exectution before restart.
I can not figure out how use two callback.
This is my code :
var getWebData = function(url) {
var data = [];
async.eachSeries(url, function(urlSingle, cb) {
request(urlSingle, function(err, resp, body) {
if (!err) {
var $ = cheerio.load(body);
var categoriesURL = [];
$('.ombre_menu li').each(function(i, element) {
$(this).find('.nav_sous-menu_bloc li a').each(function(i, element) {
categoriesURL.push('https://blabla' + $(this).attr('href'));
})
// I WANT TO LOOP on the categoriesURL array HERE
var jsObject = { name : "", description : "", price: "", categorie: "", liter: "", kilo: "", pricePer: "", quantity: "", capacity: "", promotion: "", scrapingDate : "", url: "" };
data.push(jsObject);
})
}
cb();
})
}, function() {
// this will rum when loop is done
var json = JSON.stringify(data);
fs.writeFile('output.json', JSON.stringify(json, null, 4), function(err) {
console.log('File successfully written!');
});
});
}
getWebData(url);
app.listen('8080');
Does anyone know how can I do ?
Thanks
Made couple of changes in your code:
Used .mapSeries in place of .eachSeries. This way you can get data from iterator function in same order as the input array. Means you'll get [4,9] for input [2,3] to a square function, never [9,4]
Broke code into functions so that each function does one specific task
Moved categoriesURL processing out of loop 1
Returning early. It improves code readability. if (err) return callback(err);
function getWebData(url) {
// Using .mapSeries in place of .eachSeries as you seem to want to get data from iterator function
async.mapSeries(url, processUrl, function(err, results) {
// this will rum when loop is done
var json = JSON.stringify(results);
fs.writeFile('output.json', JSON.stringify(json, null, 4), function(err) {
console.error('Error', err);
console.log('File successfully written!');
});
});
}
function processUrl(url, callback) {
request(url, function(err, resp, body) {
if (err) // Return simple cases early; Improves code readability
return callback(err); // or return callback(); -- if you don't want to send error upwards
var $ = cheerio.load(body);
var categoriesURL = [];
$('.ombre_menu li')
.each(function(i, element) { // loop 1
$(this)
.find('.nav_sous-menu_bloc li a')
.each(function(i, element) { // loop 2
categoriesURL.push('https://blablablac' + $(this)
.attr('href'));
}) // loop 2 end
}) // loop 1 end
// I WANT TO LOOP ON THE categoriesURL ARRAY HERE
// Using .mapSeries in place of .eachSeries for same above reason
async.mapSeries(categoriesURL, processCategoryUrl, function(err, results) {
if (err)
return callback(err);
// This function is called after process array categoriesURL
// Do what you want here then call callback provided to this method
return callback(null, results);
})
})
}
function processCategoryUrl(categoryUrl, callback) {
// Just process categoryUrl here and call callback with error or results
return callback();
}
getWebData(url);
app.listen('8080');
You can use nested eachSeries. Like this:
var getWebData = function(url) {
var data = [];
async.eachSeries(url, function(urlSingle, cb) {
request(urlSingle, function(err, resp, body) {
if (!err) {
var $ = cheerio.load(body);
var categoriesURL = [];
$('.ombre_menu li').each(function(i, element) {
$(this).find('.nav_sous-menu_bloc li a').each(function(i, element) {
categoriesURL.push('https://blablablac' + $(this).attr('href'));
})
async.eachSeries(caturl, function(categoriesURL, cb2) {
//Do whatever you want to do here
cb2();
}, function() {
//You can apply if and else for err an according to that you can set your callback responce here
cb();
};
})
}
})
}, function() {
// this will rum when loop is done
var json = JSON.stringify(data);
fs.writeFile('output.json', JSON.stringify(json, null, 4), function(err) {
console.log('File successfully written!');
});
});
}
getWebData(url);
app.listen('8080');

returning data from node mssql execute functions

I'm using mssql(Microsoft SQL Server client for Node.js) package from npm.I'm trying to execute a stored procedure residing in my sql server database.Everything works fine.However what I want to do is return the recordsets so that i can export this to be used in other module.Below is what I'm trying to do.
function monthlyIceCreamSalesReport (scope){
var connObj = connConfig();
connObj.conn.connect(function(err){
if(err){
console.log(err);
return;
}
connObj.req.input('Month',4);
connObj.req.input('Year',2016);
connObj.req.execute('<myStoredProcedure>', function(err, recordsets, returnValue){
if(err){
console.log(err);
}
else {
console.log(recordsets[0]); // successfully receiving the value
}
connObj.conn.close();
});
});
console.log('check for recordsets', recordsets[0]); // undefined
return recordsets[0];
}
var sqlServerObj = {
monICSalesReport : monthlyIceCreamSalesReport,
};
module.exports = sqlServerObj;
As shown in the code snippet, since the value of recordsets[0] is undefined, exporting this function is of no use.
You can't return this way in async nature. You can get it by passing the callback function
Try to give a callback function like this
function monthlyIceCreamSalesReport(scope, callback) { // pass a callback to get value
var connObj = connConfig();
connObj.conn.connect(function(err) {
if (err) {
console.log(err);
return;
}
connObj.req.input('Month', 4);
connObj.req.input('Year', 2016);
connObj.req.execute('<myStoredProcedure>', function(err, recordsets, returnValue) {
if (err) {
console.log(err);
} else {
console.log(recordsets[0]);
connObj.conn.close();
return callback(null, recordsets[0]); //return as a callback here and get that value in callback from where you called this function
}
});
});
}
var sqlServerObj = {
monICSalesReport: monthlyIceCreamSalesReport,
};
module.exports = sqlServerObj;
Note: See the comment to understand the changes
recordsets[0] is undefinded, because is defined only in connObj.req.execute function scope. You may do this in this way:
function monthlyIceCreamSalesReport (scope, cb){
var connObj = connConfig();
connObj.conn.connect(function(err){
if(err){
console.log(err);
return cb(Error("Something wrong"));
}
connObj.req.input('Month',4);
connObj.req.input('Year',2016);
connObj.req.execute('<myStoredProcedure>', function(err, recordsets, returnValue){
if(err){
console.log(err);
connObj.conn.close();
return cb(Error("Something wrong"));
}
else {
console.log(recordsets[0]); // successfully receiving the value
connObj.conn.close();
return cb(recordsets[0]);
}
});
});
}
var sqlServerObj = {
monICSalesReport : monthlyIceCreamSalesReport,
};
module.exports = sqlServerObj;

How to wait for a response from a mongo findOne query in a node/express app before using the response in following control flow

I am new to node, and also JavaScript callbacks.
I am trying to check if an account exists in mongo and then 'save it' if it doesn't and return an error if it does.
I am currently trying to figure this out outside of my express app. This is what i have..
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/main', function (err, db) {
if(err) throw err;
var query = { name : "www.website.com"}
findOne(db, query, function (doc) {
if(doc) {
console.log('account exists');
} else {
console.log('good to go');
}
console.dir(doc);
});
});
var findOne = function (db, query, callback) {
db.collection('accounts').findOne(query, function (err, doc) {
if(err) throw err;
db.close();
callback();
});
}
with the console.dir(doc); above returning as undefined. How do I wait for the findOne to return before using the callback to console.log or save the account?
The reason you are getting undefined is because when you call your callback your are not passing it the doc. That line should look like callback(doc).
Here is an updated version of your code with a few suggestions:
MongoClient.connect('mongodb://localhost:27017/main', function (err, db) {
if(err) throw err;
var query = { name : "www.website.com"}
findOne(db, query, function (err, doc) {
if(err) {
// something went wrong
console.log(err);
return;
}
if(doc) {
console.log('account exists');
console.dir(doc);
} else {
console.log('good to go');
}
});
});
var findOne = function (db, query, callback) {
db.collection('accounts').findOne(query, function (err, doc) {
db.close();
if(err) {
// don't use throw when in async code
// the convention is to call your callback with the error
// as the first argument (notice that I added an argument
// to the definition of your callback above)
callback(err);
}
else {
// call your callback with no error and the data
callback(null, doc);
}
});
}

Categories

Resources