Q.fcall always goes into fail - javascript

var Q = require('q')
var fs = require('fs')
var deferred = Q.defer()
function GetDTImage (PicName) {
fs.readFile(process.cwd() + '\\' + PicName + '.jpg', function (error, text) {
if (error) {
console.log(error)
} else {
return text.toString('base64')
}
})
}
Q.fcall(GetDTImage('Dogs'))
.then(
function (imgBase64Code) {
console.log(imgBase64Code)
}, function (err) {console.log(err)}
)
Hello everyone, here is a question bothering me for a time.
I am confused why the above code always performs the error message, Cannot read property 'apply' of undefined,

Firstly, Q.fcall expects a function as the first argument, and optional arguments for that function as subsequent arguments
so, you need to use Q.fcall like this
Q.fcall(GetDTImage, 'Dogs')
.then(
function (imgBase64Code) {
console.log(imgBase64Code)
}, function (err) {console.log(err)}
)
However, this would resolve to the value (or promise) returned by calling
GetDTImage('Dogs')
But your function GetDTImage doesn't return anything - the only return statement is inside the callback inside that function!
effectively your GetDTImage funciton is
function GetDTImage (PicName) {
// go and do this asynchronous thing
fs.readFile(process.cwd() + '\\' + PicName + '.jpg', function (error, text) {
if (error) {
return reject(error);
}
resolve(text.toString('base64'));
});
// but return straight away regardless of that asynchronous thing
return undefined;
}
because fs.readFile is asynchronous, you need GetDTImage to return a promise for it to work
function GetDTImage (PicName) {
// here we return a promise, huzzah!
return new Promise(function (resolve, reject) {
fs.readFile(process.cwd() + '\\' + PicName + '.jpg', function (error, text) {
if (error) {
return reject(error);
}
resolve(text.toString('base64'));
});
});
}
Now you can either
Q.fcall(GetDTImage, 'Dogs')
.then(
function (imgBase64Code) {
console.log(imgBase64Code)
}, function (err) {console.log(err)}
)
or
Q.fcall(GetDTImage('Dogs'))
.then(
function (imgBase64Code) {
console.log(imgBase64Code)
}, function (err) {console.log(err)}
)
(I'm sure there's a difference between those two, but I'm not familiar enough with Q to accurately define that difference
However, since GetDTImage now returns a promise, you may as well do this:
GetDTImage('Dogs')
.then(
function (imgBase64Code) {
console.log(imgBase64Code)
}, function (err) {console.log(err)}
)
and forget Q.fcall altogether

var Q = require('q')
var fs = require('fs')
var deferred = Q.defer()
function GetDTImage (PicName) {
fs.readFile(process.cwd() + '\\' + PicName + '.jpg', function (error, text) {
if (error) {
console.log(error)
} else {
deferred.resolve(text.toString('base64'))
}
})
return deferred.promise
}
GetDTImage(Dogs)
.then(
function (imgBase64Code) {
console.log(imgBase64Code)
}, function (err) {console.log(err)}
)
Thanks Jaromanda's support.
I have solved it and here is my solution.

Related

ldapjs client.search results to be accessed outside of the function

I am using ldapjs library in nodejs. I want to access the results of client.search outside of the function.
Here is my code
items = [];
client.search('cn=users,dc=test,dc=com', opts, function (err, res) {
if (err)
console.log(err);
res.on('searchEntry', function (entry) {
items.push(entry.object);
});
res.on('error', function (err) {
console.error('error: ' + err.message);
});
res.on('end', function (result) {
console.log('status: ' + result.status);
console.log(items[0]); **//Prints results correctly**
});
});
console.log(items[0]); **//Prints []**
I tried return items inside search. Still doesn't print. Any suggestions?
I encountered the same problem. Since res.on 'searchEntry' is an event emitter
, a simple solution that I use is to wrap the whole thing in a promise and return that.
let search = function( 'cn=users,dc=test,dc=com', opts ) {
return new Promise( ( resolve, reject ) => {
items = [];
client.search('cn=users,dc=test,dc=com', opts, function (err, res) {
if (err)
console.log(err);
reject( err )
res.on('searchEntry', function (entry) {
items.push(entry.object);
});
res.on('error', function (err) {
console.error('error: ' + err.message);
reject( error )
});
res.on('end', function (result) {
console.log('status: ' + result.status);
console.log(items[0]); **//Prints results correctly**
resolve( items )
});
});
}
};
Then you can do something like this:
let entries = await search( 'cn=users,dc=test,dc=com', opts );
You can use a wrapper function and a callback
function search(dn, options, callback){
// your code ...
res.on('end', function (result) {
callback(items);
}
});
and to call it like this
search(dn, options, function(err, result) {
//your result ...
console.log(result);
}

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

Returning a bluebird promise to electrons renderer process

Im using Electron's remote function to call a node module which returns a bluebird promise. However, I can't figure out how to get the promise returned back to the renderer process thats calling the module.
Using this code the value of return_data1 is always empty.
exports.call_python = function () {
data1 = []
var Promise = require('bluebird');
var exec = require('child_process').execFile;
function promiseFromChildProcess(child) {
return new Promise(function (resolve, reject) {
child.addListener("error", reject);
child.addListener("exit", resolve);
});
}
var child = exec('ls');
promiseFromChildProcess(child).then(function (result) {
console.log('promise complete: ' + result);
}, function (err) {
console.log('promise rejected: ' + err);
});
child.stdout.on('data', function (data) {
console.log('stdout: ' + data);
data.push={data: data}
});
child.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
child.on('close', function (code) {
console.log('closing code: ' + code);
});
return data1
};
Once you jump into Promises it's pretty much promises all the way down. You can unwrap a Promise to get back to callback semantics but unless you are writing a service for pre-Promise API why would you?
In this case don't return data1; return the resolved promise. e.g.:
return promiseFromChildProcess(child).then(function (result) {
console.log('promise complete: ' + result);
return result;
}, function (err) {
console.log('promise rejected: ' + err);
return '';
});
or if the client should deal with the error just:
return promiseFromChildProcess(child);
It sounds like maybe you are unsure of how to use child_process. The really simple way is to just grab stdout after the child process exits:
var b = require('bluebird');
var cp = require('child_process');
new b(function(resolve, reject){
cp.exec('dir', function(err, stdout, stderr){
resolve(stdout);
});
}).then(function(data){
console.log("dir is "+data);
});
so do:
exports.call_python = function () {
var b = require('bluebird');
var cp = require('child_process');
return new b(function(resolve, reject){
cp.exec('ls', function(err, stdout, stderr){
resolve(stdout);
});
});
};

how to make synchronous http calls within async.each in nodejs

I want to make http requests to an API-s to collect for each user it's data and insert into mongodb.
The problem I am having is, it is doing all the requests at once, and seems it gets stuck somewhere and I don't know what is going on.
Al thou I am using async library and add the request() method inside each iteration, and I dont know if this is the right way, here is the code:
function iterateThruAllStudents(from, to) {
Student.find({status: 'student'})
.populate('user')
.exec(function (err, students) {
if (err) {
throw err;
}
async.forEach(students, function iteratee(student, callback) {
if (student.worksnap.user != null) {
var options = {
url: 'https://api.worksnaps.com/api/projects/' + project_id + '/time_entries.xml?user_ids=' + student.worksnap.user.user_id + '&from_timestamp=' + from + '&to_timestamp=' + to,
headers: {
'Authorization': 'Basic bGhNSVJkVUFwOE1DS2loOFVyZkFyOENEZEhPSXdCdUlHdElWMHo0czo='
}
};
request(options, getTimeEntriesFromWorksnap);
}
callback(); // tell async that the iterator has completed
}, function (err) {
console.log('iterating done');
});
});
}
function getTimeEntriesFromWorksnap(error, response, body) {
console.log(response.statusCode);
if (!error && response.statusCode == 200) {
parser.parseString(body, function (err, results) {
var json_string = JSON.stringify(results.time_entries);
var timeEntries = JSON.parse(json_string);
_.forEach(timeEntries, function (timeEntry) {
_.forEach(timeEntry, function (item) {
saveTimeEntry(item);
});
});
});
}
}
function saveTimeEntry(item) {
Student.findOne({
'worksnap.user.user_id': item.user_id[0]
})
.populate('user')
.exec(function (err, student) {
if (err) {
throw err;
}
student.timeEntries.push(item);
student.save(function (err) {
if (err) {
console.log(err);
} else {
console.log('item inserted...');
}
});
});
}
var from = new Date(startDate).getTime() / 1000;
startDate.setDate(startDate.getDate() + 30);
var to = new Date(startDate).getTime() / 1000;
iterateThruAllStudents(from, to);
I am new to JavaScript, especially when dealing with async.
Any help?
Use Async.eachLimit() to make batched request to the api...Try this iterateThruAllStudents() function.
I already had same question before here
See tutorial of limiting here.
Though i am making the limit as 5 but you can do whatever you want(10,50 etc).
function iterateThruAllStudents(from, to) {
Student.find({status: 'student'})
.populate('user')
.exec(function (err, students) {
if (err) {
throw err;
}
async.eachLimit(students,5,function iteratee(student, callback) {
if (student.worksnap.user != null) {
var options = {
url: 'https://api.worksnaps.com/api/projects/' + project_id + '/time_entries.xml?user_ids=' + student.worksnap.user.user_id + '&from_timestamp=' + from + '&to_timestamp=' + to,
headers: {
'Authorization': 'Basic bGhNSVJkVUFwOE1DS2loOFVyZkFyOENEZEhPSXdCdUlHdElWMHo0czo='
}
};
request(options,getTimeEntriesFromWorksnap(callback));
}
}, function (err) {
console.log(err);
console.log('iterating done');
});
});
}
function getTimeEntriesFromWorksnap(cb) {
return function(error, response, body){
console.log(response.statusCode);
if (!error && response.statusCode == 200) {
parser.parseString(body, function (err, results) {
var json_string = JSON.stringify(results.time_entries);
var timeEntries = JSON.parse(json_string);
async.each(timeEntries,function(timeEntry,cb1){
async.each(timeEntry,function(item,cb2){
saveTimeEntry(item,cb2);
},function(err){
if(err)
cb1(err);
else
cb1();
})
},function(err){
if(err)
cb(err);
else
cb();
});
//_.forEach(timeEntries, function (timeEntry) {
// _.forEach(timeEntry, function (item) {
// saveTimeEntry(item);
// });
//});
});
}
cb(null);
}
}
function saveTimeEntry(item,cb2) {
Student.findOne({
'worksnap.user.user_id': item.user_id[0]
})
.populate('user')
.exec(function (err, student) {
if (err) {
return cb2(err);
}
student.timeEntries.push(item);
student.save(function (err) {
if (err) {
console.log(err);
//return cb2(err);//Do it if you wanna throw an error.
} else {
console.log('item inserted...');
}
cb2();
});
});
}
var from = new Date(startDate).getTime() / 1000;
startDate.setDate(startDate.getDate() + 30);
var to = new Date(startDate).getTime() / 1000;
iterateThruAllStudents(from, to);
In your example you missed iteratee param in the each method of async - iteratee(item, callback). Look at this example here.
You need to call callback each time inside your iteratee function to tell async continue doing its processing.
each(collection, iteratee, [callback])
collection - collection to iterate over.
iteratee(item, callback) - function to apply to each item in coll. The iteratee is passed a callback(err) which must be called once it has completed. If no error has occurred, the callback should be run without arguments or with an explicit null argument. The array index is not passed to the iteratee. If you need the index, use forEachOf.
callback(err) - Optional callback which is called when all iteratee functions have finished, or an error occurs.
If you need synchronous behavior, no probs! There is also eachSeries method with the same signature except every collection item will be iterated synchronously.
UPDATE:
Changes should be implemented:
Pass async callback:
request(options, getTimeEntriesFromWorksnap(callback));
Return necessary for request callback function:
function getTimeEntriesFromWorksnap(callback) {
return function(error, response, body) {
// ...
saveTimeEntry(item, callback);
// ...
}
}
Call callback only after record is saved in database:
function saveTimeEntry(item, callback) {
// ..
student.save(callback);
// ..
}
Refactor nested loops (not sure what timeEntries, timeEntry are, so use appropriate async method to iterate these data structures):
async.each(timeEntries, function (timeEntry, callback) {
async.each(timeEntry, function (item, callback) {
saveTimeEntry(item, callback);
}, callback);
}, callback);

How to make synchronous http call using Promises in Nodejs

I would like to make http call synchronously using Q Promises, I have 100 students that I need for each of them to take some data from another platform and to do that I was trying via Q Promises but it does not seem like it is doing synchronously.
How do I make sure that another call is not being made once one is finished with parsing it's response and insertion into mongodb:
my code so far looks like this:
var startDate = new Date("February 20, 2016 00:00:00"); //Start from February
var from = new Date(startDate).getTime() / 1000;
startDate.setDate(startDate.getDate() + 30);
var to = new Date(startDate).getTime() / 1000;
iterateThruAllStudents(from, to);
function iterateThruAllStudents(from, to) {
Student.find({status: 'student'})
.populate('user')
.exec(function (err, students) {
if (err) {
throw err;
}
async.eachSeries(students, function iteratee(student, callback) {
if (student.worksnap.user != null) {
var worksnapOptions = {
hostname: 'worksnaps.com',
path: '/api/projects/' + project_id + '/time_entries.xml?user_ids=' + student.worksnap.user.user_id + '&from_timestamp=' + from + '&to_timestamp=' + to,
headers: {
'Authorization': 'Basic xxxx='
},
method: 'GET'
};
promisedRequest(worksnapOptions)
.then(function (response) { //callback invoked on deferred.resolve
parser.parseString(response, function (err, results) {
var json_string = JSON.stringify(results.time_entries);
var timeEntries = JSON.parse(json_string);
_.forEach(timeEntries, function (timeEntry) {
_.forEach(timeEntry, function (item) {
saveTimeEntry(item);
});
});
});
callback();
}, function (newsError) { //callback invoked on deferred.reject
console.log(newsError);
});
}
});
function saveTimeEntry(item) {
Student.findOne({
'worksnap.user.user_id': item.user_id[0]
})
.populate('user')
.exec(function (err, student) {
if (err) {
throw err;
}
student.timeEntries.push(item);
student.save(function (err) {
if (err) {
console.log(err);
} else {
console.log('item inserted...');
}
});
});
}
function promisedRequest(requestOptions) {
//create a deferred object from Q
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
var deferred = Q.defer();
var req = http.request(requestOptions, function (response) {
//set the response encoding to parse json string
response.setEncoding('utf8');
var responseData = '';
//append data to responseData variable on the 'data' event emission
response.on('data', function (data) {
responseData += data;
});
//listen to the 'end' event
response.on('end', function () {
//resolve the deferred object with the response
console.log('http call finished');
deferred.resolve(responseData);
});
});
//listen to the 'error' event
req.on('error', function (err) {
//if an error occurs reject the deferred
deferred.reject(err);
});
req.end();
//we are returning a promise object
//if we returned the deferred object
//deferred object reject and resolve could potentially be modified
//violating the expected behavior of this function
return deferred.promise;
}
Anyone could tell me what do I need to do to achieve such things?
Is it also possible so that I know when all of the http calls are finished and the insertion is done for all...
I would abandon your current approach and use the npm module request-promise.
https://www.npmjs.com/package/request-promise
It's very popular and mature.
rp('http://your/url1').then(function (response1) {
// response1 access here
return rp('http://your/url2')
}).then(function (response2) {
// response2 access here
return rp('http://your/url3')
}).then(function (response3) {
// response3 access here
}).catch(function (err) {
});
Now you just need to convert this to some kind of iteration for the 100 requests you want and the job will be done.

Categories

Resources