Error while using async.parallel - javascript

I am getting binding error while using async in node.js. The code in question:
var async = require('async');
var fs = require('fs');
var path = require('path');
function ignoreWhiteSpaceJudge(outDesired, outGenerated){
var contentOutDesired = "";
var contentOutGenerated = "";
async.parallel([
function(outDesired, callback) {
console.log(outDesired);
fs.readFile(outDesired, 'utf8',function(error, data) {
if (error) {
return callback(error);
} else {
contentOutDesired = data;
return callback();
}
});
},
function(outGenerated, callback) {
fs.readFile(outGenerated, 'utf8', function(error, data) {
if (error) {
return callback(error);
} else {
ontentOutGenerated = data;
return callback();
}
});
}],
function(error){
if(error){
console.log(error);
}
else{
console.log(contentOutDesired);
console.log(ontentOutGenerated);
}
});
}
var pathToOutDesired = path.normalize('/home/repos/gabbar/testcases/outputs/output_1_1.out');
var pathToOutGenerated = path.normalize('/home/repos/gabbar/testcases/outputs/output_1_2.out');
ignoreWhiteSpaceJudge(pathToOutDesired, pathToOutGenerated);
The error I am getting looks like this:
[Function]
fs.js:423
binding.open(pathModule._makeLong(path),
^
TypeError: path must be a string
at Object.fs.open (fs.js:423:11)
at Object.fs.readFile (fs.js:206:6)
at async.parallel.fs.readFile.ontentOutGenerated (/home/repos/gabbar/validation/ignoreWhiteSpaceJudge.js:17:18)
at /home/repos/gabbar/node_modules/async/lib/async.js:570:21
at /home/repos/gabbar/node_modules/async/lib/async.js:249:17
at /home/repos/gabbar/node_modules/async/lib/async.js:125:13
at Array.forEach (native)
at _each (/home/repos/gabbar/node_modules/async/lib/async.js:46:24)
at async.each (/home/repos/gabbar/node_modules/async/lib/async.js:124:9)
at _asyncMap (/home/repos/gabbar/node_modules/async/lib/async.js:248:13)
I am relatively new to node.js and trying to use async module for the first time. Could somebody help me in this regard?

You are overwriting your paths with the callback function of parallel.
Just remove the first parameter from your functions which is the callback and not your data:
function(callback) {
console.log(outDesired);
fs.readFile(outDesired, 'utf8',function(error, data) {
if (error) {
return callback(error);
} else {
contentOutDesired = data;
return callback();
}
});
},
function(callback) {
fs.readFile(outGenerated, 'utf8', function(error, data) {
if (error) {
return callback(error);
} else {
ontentOutGenerated = data;
return callback();
}
});
}

Related

node.js warning when calling to function

I've the following code which works
if (fs.existsSync(dirName)) {
__writeFile();
return;
}
function __writeFile() {
writeIntoFile(readStream, destFileName, reject);
numOfFiles++;
}
But after execute it im getting warning:
(node:3547) [DEP0013] DeprecationWarning: Calling an asynchronous
function without callback is deprecated.
Any idea how to avoid this ?
update this is all the code
yauzl.open(filePath, (err, zipFile) => {
if (err) {
__rejectAndLog(err);
return;
}
zipFile.on('entry', __processEntry.bind(null, zipFile))
.once('error', __rejectAndLog)
.once('close', () => {
resolve();
});
});
function __processEntry(zipFile, entry) {
if (/\/$/.test(entry.fileName)) {
return;
}
zipFile.openReadStream(entry, (err, readStream) => {
if (err) {
__rejectAndLog(err);
return;
}
//Path to drop the files
let destFileName = '/' + entry.fileName;
let dirName = path.join(res);
if (fs.existsSync(dirName)) {
__writeFile();
return;
}
mkdirp(dirName, (err) => {
if (err) {
__rejectAndLog(err);
} else {
__writeFile();
}
});
function __writeFile() {
writeIntoFile(readStream, destFileName, reject);
numOfFiles++;
}
});
}
as requested this is the content of write into file
function writeIntoFile(readStream, filePath, onError) {
if (fs.existsSync(filePath)) {
fs.chmod(filePath, '777');
}
var ws = fs.createWriteStream(filePath);
ws.on('error', function (error) {
onError(error);
});
readStream.pipe(ws);
};
update2
I try to change it according the answer below and its not working (and where should I put the mode 777)
function writeIntoFile(readStream, filePath, onError) {
if (fs.existsSync(filePath)) {
fs.chmod(filePath, 0o777, function (err) {
var ws = fs.createWriteStream(filePath);
ws.on('error', function (error) {
onError(error);
});
readStream.pipe(ws);
});
}
};

Make multiple callbacks from node js asynchronous function

How can I return a object of data returned by asynchronous function called multiple times from within a asynchronous function.
I'm trying to implement like this :
var figlet = require('figlet');
function art(dataToArt, callback)
{
var arry[];
figlet(dataToArt, function(err, data) {
if (err) {
console.log('Something went wrong...');
console.dir(err);
return callback('');
}
arry[0] = data;
callback(arry);
});
figlet(dataToArt, function(err, data) {
if (err) {
console.log('Something went wrong...');
console.dir(err);
return callback('');
}
arry[1] = data;
callback(arry);
});
}
art('Hello World', function (data){
console.log(data);
});
How can I do it correctly, I searched and searched but couldn't find a solution.
Ps. I'm using Figlet.js
I don't know if you're ok using an external module, but you can use tiptoe.
Install it using npm install tiptoe like any regular module and it basically goes like this:
var tiptoe = require('tiptoe')
function someAsyncFunction(obj, callback) {
// something something
callback(null, processedData);
}
tiptoe(
function() {
var self = this;
var arr = ['there', 'are', 'some', 'items', 'here'];
arr.forEach(function(item) {
someAsyncFunction(item, self.parallel());
});
},
function() {
var data = Array.prototype.slice.call(arguments);
doSomethingWithData(data, this);
},
function(err) {
if (err) throw (err);
console.log('all done.');
}
);
the someAsyncFunction() is the async function you want to call does something and calls the callback parameter as a function with the parameters error and data. The data parameter will get passed as an array item to the following function on the tiptoe flow.
Did it Myself :) Thanks to mostafa-samir's post
var figlet = require('figlet');
function WaterfallOver(list, iterator, callback) {
var nextItemIndex = 1;
function report() {
nextItemIndex++;
if(nextItemIndex === list.length)
callback();
else
iterator([list[0],list[nextItemIndex]], report);
}
iterator([list[0],list[1]], report);
}
var FinalResult = [];
WaterfallOver(["hello","Standard","Ghost"], function(path, report) {
figlet.text(path[0], { font: path[1] }, function(err, data) {
if (err) {
FinalResult.push("Font name error try help");
report();
return;
}
data = '<pre>.\n' + data + '</pre>';
FinalResult.push(data);
report();
});
}, function() {
console.log(FinalResult[0]);
console.log(FinalResult[1]);
});

Callback is not a function in mongoose.find({})

I am new to Node.js and mongoose, i am trying to query objects from a mongo collection using find({}) and the function is as follows :
schema.statics.listAllQuizes = function listAllQuizes(){
Model.find({},function(err,quizes,cb){
if(err){
return cb(err);
}else if(!quizes){
return cb();
}
else {
return cb(err,quizes);
}
});};
But when i call this function i get an error saying
return cb(err,quizes);
^
TypeError: cb is not a function
I am stuck at this point, can someone please help me with this, thanks in advance.
The callback should an argument to listAllQuizes, not an argument to the anonymous handler function.
In other words:
schema.statics.listAllQuizes = function listAllQuizes(cb) {
Model.find({}, function(err, quizes) {
if (err) {
return cb(err);
} else if (! quizes) {
return cb();
} else {
return cb(err, quizes);
}
});
};
Which, logically, is almost the same as this:
schema.statics.listAllQuizes = function listAllQuizes(cb) {
Model.find({}, cb);
};
Here's an example on how to use it:
var quiz = App.model('quiz');
function home(req, res) {
quiz.listAllQuizes(function(err, quizes) {
if (err) return res.sendStatus(500);
for (var i = 0; i < quizes.length; i++) {
console.log(quizes[i].quizName)
}
res.render('quiz', { quizList : quizes });
});
}
Assuming you have code somewhere that looks like this:
foo.listAllQuizzes(function (err, quizzes) {
...
});
Then your function listAllQuizzes is passed a callback:
schema.statics.listAllQuizzes = function (cb) {
Model.find({}, function(err, quizzes) {
if (err) return cb(err);
cb(null, quizzes);
});
};

Find inside callback of another find (...), how to escape from callback hell?

(First: I'm sorry, I don't speak english very well!)
I wanna return the results of 3 finds in one array.
My code (next) is running well, but I'm in callback hell!
_Schema
.static('retrieveAll', function(cb) {
query = {};
this.find(query, function(err, data) {
if(err) {
cb(err, null);
return;
}
if(data)
all = data;
else
all = [];
_StoresModel.find(query).select('contact address').exec(function(err, data) {
if(err) {
cb(err, null);
return;
}
if(data) {
all = data.reduce(function(coll, item) {
coll.push(item);
return coll;
}, all);
}
_CustomersModel.find(query).select('contact address').exec(function(err, data) {
if(err) {
cb(err, null);
return;
}
if(data) {
all = data.reduce(function(coll, item) {
coll.push(item);
return coll;
}, all);
}
cb(null, all);
});
});
});
});
I've a FIND inside a FIND inside a FIND.
Is there anyway to improve this?
SOLUTION:
_Schema
.static('retrieveAll', function(cb) {
var model = this;
_async.parallel(
{ contacts: function(cb) {
model.find({}).exec(cb);
}
, stores: function(cb) {
_StoresModel.find({}).select('contact address').exec(cb);
}
, costumers: function(cb) {
_CostumersModel.find({}).select('contact address').exec(cb);
}
}
, function(err, data) {
if(err) {
cb(err, null);
return
}
var ret = [];
if(data.contacts.length > 0) {
ret = ret.concat(data.contacts);
}
if(data.stores.length > 0) {
ret = ret.concat(data.stores);
}
if(data.costumers.length > 0) {
ret = ret.concat(data.costumers);
}
cb(null, ret);
});
You can try using Promises.
(untested) example:
var RSVP = require('rsvp');
var all = [];
_Schema.static('retrieveAll', function(cb) {
query = {};
findPromise(this, query)
.then(function (data) {
all = data;
return findPromise(_StoresModel, query, 'contact address');
})
.then(function (stores) {
all = all.concat(stores);
return findPromise(_CustomersModel, query, 'contact address');
})
.then(function (customers) {
all = all.concat(customers);
cb(null, all);
})
.catch(function (err) {
cb(err, null);
});
});
function findPromise(Model, query, select) {
return new RSVP.Promise(function (resolve, reject) {
Model.find(query).select(select || '*').exec(function (err, data) {
return err ? reject(err) : resolve(data);
});
});
}
That example is using RSVP, but there are also other promise implementations such as Q and bluebird.
And a side note, you can use concat to concatenate arrays instead of using reduce.
take a look at npm Async. It a great library of different patterns that can be used on node.js.
You will probably want to use the waterfall if there is a Chronological priority or parallel pattern if they can all execute in parallel.
Some server-side promise libraries like q and bluebird would clean up your code substantially and eliminate the mess of callback hell.

Uploading to dropbox via node js fails

I have the following code to read from a stream and upload to Dropbox. But I'm getting a
Uncaught TypeError: Cannot call method 'toString' of undefined
at Function.Dropbox.Util.Xhr.Xhr.urlEncodeValue (node_modules\dropbox\lib\dropbox.js:3695:40)
at Function.Dropbox.Util.Xhr.Xhr.urlEncode (node_modules\dropbox\lib\dropbox.js:3689:59)
at Xhr.Dropbox.Util.Xhr.Xhr.paramsToUrl (node_modules\dropbox\lib\dropbox.js:3570:40)
at Xhr.Dropbox.Util.Xhr.Xhr.prepare (node_modules\dropbox\lib\dropbox.js:3598:14)
at Client.Dropbox.Client.Client._dispatchXhr (node_modules\dropbox\lib\dropbox.js:2137:11)
at Client.Dropbox.Client.Client.resumableUploadStep (node_modules\dropbox\lib\dropbox.js:1454:19)
.....
error when I try to run the code.If I give a 'false' as cursor, the error doesn't occur in step function, but still it occures in finish function. Can anyone help me on this?
stream.on('data', function (data) {
client.resumableUploadStep(data, function (error, cursor) {
if (error) {
return console.log(error);
}
})
});
stream.on('end', function () {
client.resumableUploadFinish(fileName, function (error, stats) {
if (error) {
return callback(error);
}
return callback(null, stats);
});
});
I used the following code and now it works.
var pcursor = null;
var eventObject = new EventEmitter();
var counter = 0;
stream.on('data', function (data) {
counter++;
client.resumableUploadStep(data, pcursor, function (error, cursor) {
if (error) {
return callback(error);
}
counter--;
pcursor = cursor;
eventObject.emit('event');
});
});
stream.on('end', function () {
eventObject.on('event', function () {
if (counter == 0) {
client.resumableUploadFinish(fileName, pcursor, function (error, stats) {
if (error) {
return callback(error);
}
return callback(null, stats);
});
counter = -1;
}
});
eventObject.emit('event');
});
It looks like you're missing the cursor parameter to resumableUploadFinish. Also, you should be passing in a cursor to resumableUploadStep after the first call too.
I think the code you want is something like this (completely untested):
var cursor = null;
stream.on('data', function (data) {
client.resumableUploadStep(data, cursor, function (error, new_cursor) {
cursor = new_cursor;
});
});
stream.on('end', function () {
client.resumableUploadFinish(fileName, cursor, function (error, stats) {
return callback(null, stats);
});
});

Categories