NodeJS How to create asynchronus function and then call it - node.js

I want to make a function to list the file in some directory, and filtered it by extension:
here is my code look like:
var fs = require('fs'),
path = require('path');
var filterList = function (path, ext) {
return fs.readdir(path, function (err, files) {
if (err) {
console.log(err);
} else {
for (var i = 0; i < files.length; i++) {
if (path.extname(files[i]) === '.' + ext) {
return console.log(files[i]);
}
}
}
});
};
filterList(process.argv[2], process.argv[3]);
but it returns this error:
if (path.extname(files[i]) === '.' + ext) {
^
TypeError: path.extname is not a function
Any idea why?

Change name of arg from path to _path, its conflicting
var fs = require('fs'),
path = require('path');
var filterList = function (_path, ext) {
return fs.readdir(_path, function (err, files) {
if (err) {
console.log(err);
} else {
for (var i = 0; i < files.length; i++) {
if (path.extname(files[i]) === '.' + ext) {
return console.log(files[i]);
}
}
}
});
};
filterList(process.argv[2], process.argv[3]);

Related

Node js Promises with recursive function

I want to read the all (text) files from a specific directory and it's all subdirecoty recursively.. I am able to read the file and append the result to a global variable. but i want to access the variable at the end of all operation. I am trying with promises but i am unable to access it. please help
var file_path = `C:\\Users\\HP\\Desktop\\test_folder`;
const fs = require('fs');
var final_array = [];
let getFolderTree = function(file_path) {
return new Promise(function(resolve, reject) {
fs.readdir(file_path, function(err, folders) {
if (err) {
console.log("error reading folder :: " + err);
} else {
if (folders.length !== 0) {
for (let i = 0; i < folders.length; i++) {
if (folders[i].endsWith("txt")) {
let text_file_path = file_path + `\\` + folders[i];
fs.readFile(text_file_path, function(error_read, data) {
if (error_read) {
console.log("error reading " + error_read);
} else {
return resolve(final_array.push(data));// want to access final_array at the end of all operations
}
});
} else {
let current_path = file_path + `\\` + folders[i];
getFolderTree(current_path);
}
}
}
}
});
});
}
getFolderTree(file_path).then(function() {
console.log(final_array); // this is not working
});
I think i have found the solution but I am still confused about how it works.
I took reference from another code and able to figure out some how.
var fs = require('fs');
var path = require('path');
let root_path = "C:\\Users\\HP\\Desktop\\test_folder";
function getAllDirectoriesPath(current_path) {
var results = [];
return new Promise(function (resolve, reject) {
fs.readdir(current_path, function (erro, sub_dirs) {
if (erro) {
console.log(error);
} else {
let no_of_subdir = sub_dirs.length;
if (!no_of_subdir) {
return resolve(results);
} else {
sub_dirs.forEach(function (dir) {
dir = path.resolve(current_path, dir);
fs.stat(dir, function (err, stat) {
if (stat && stat.isDirectory()) {
getAllDirectoriesPath(dir).then(function (res) {
results = results.concat(res);
if (!--no_of_subdir) {
resolve(results);
}
});
} else {
fs.readFile(dir, function (err, data) {
results.push(data.toString());
if (!--no_of_subdir) {
resolve(results);
}
});
}
});
});
}
}
});
});
}
getAllDirectoriesPath(root_path).then(function (results) {
console.log(results);
});

Node.js reading textfiles in current directory and validate

This is actually the answer from my previous question.... the supplied code works for me. All I needed to do was retain a file counter (global) and in the read after validating add to array (global) which gets passed back to rendering process.
// Called from Render Process.
ipcMain.on('search-text-files', (event, arg) => {
const fs = require('fs');
const path = require('path');
var txtArr = [];
var fileName = '';
var fCtr = 0;
fs.readdir(__dirname+'/', function (err, items) {
if (err) {
throw err;
}
// loop through directory items
for (var i=0; i<items.length; i++) {
if (path.extname(items[i].toString() == '.txt') {
fctr+=1;
fileName = items[i].toString();
// read the file & validate
fs.readfile(__dirname+'/'+fileName, (err, data) {
if (err) {
throw err;
}
var checkArr[];
var curFile = '';
checkArr = data.toString().split('\r');
// access contents line by line
for (var line=0; line<checkArr.length; line++) {
... perform some sort of validation
... assign curFile from contents
}
if (file is valid) {
txtArr.push(curfile);
}
fCtr-=1;
if (fCtr == 0) {
event.sender.send('text-files-found', txtArr);
}
});
}
}
});
});

Need to list each file name in node before results of the function

Im using node to check through a directory tree and tell me all of the empty values in a set of JSON files. The following code, however, is returning the file path list and then the results of the function. I want each filename to precede its results so:
Filename
result
result
Filename
result...
var glob = require("glob"),
fs = require('fs');
glob("**/*/locales/*/*.json", function (er, files) {
for(var i = 0; i < files.length; i++ ){
console.log(files[i]);
fs.readFile(files[i], 'utf8', function (err,data) {
if (err) {
return console.log(err);
}
var local = JSON.parse(data);
checkStr(local);
});
}
});
function checkStr (obj, parent) {
var parent = parent || "";
if (parent.length > 0) {parent = parent + '.'}
for(key in obj) {
if(typeof(obj[key]) === "object" && obj.hasOwnProperty(key)){
checkStr(obj[key], key);
}
else {
if(!obj[key].valueOf()){
console.log( "This is empty: " + parent + key );
}
}
}
}
This should work:
var glob = require('glob');
var fs = require('fs');
function isObjectEmpty(obj) {
for (var name in obj) {
return false;
}
return true;
}
function findEmptyKey(parent, obj) {
var result = [];
for (var key in obj) {
if(typeof obj[key] === "object") {
if (isObjectEmpty(obj[key])) {
result.push(parent + '\\' + key);
} else {
Array.prototype.push.apply(result, findEmptyKey(key, obj[key]));
}
} else if (!obj[key]) {
result.push(parent + '\\' + key);
}
}
return result;
}
function processFile(file) {
fs.readFile(file, 'utf8', function (err,data) {
var keys = findEmptyKey('', JSON.parse(data));
if (keys.length>0) {
console.log(file);
keys.forEach(function(key) { console.log('This is empty: ' + key); });
}
});
}
glob("**/*/locales/*/*.json", function (er, files) {
files.forEach(processFile);
});

How to know non blocking Recursive job is complete in nodejs

I have written this non-blocking nodejs sample recursive file search code, the problem is I am unable to figure out when the task is complete. Like to calculate the time taken for the task.
fs = require('fs');
searchApp = function() {
var dirToScan = 'D:/';
var stringToSearch = 'test';
var scan = function(dir, done) {
fs.readdir(dir, function(err, files) {
files.forEach(function (file) {
var abPath = dir + '/' + file;
try {
fs.lstat(abPath, function(err, stat) {
if(!err && stat.isDirectory()) {
scan(abPath, done);;
}
});
}
catch (e) {
console.log(abPath);
console.log(e);
}
matchString(file,abPath);
});
});
}
var matchString = function (fileName, fullPath) {
if(fileName.indexOf(stringToSearch) != -1) {
console.log(fullPath);
}
}
var onComplte = function () {
console.log('Task is completed');
}
scan(dirToScan,onComplte);
}
searchApp();
Above code do the search perfectly, but I am unable to figure out when the recursion will end.
Its not that straight forward, i guess you have to rely on timer and promise.
fs = require('fs');
var Q = require('q');
searchApp = function() {
var dirToScan = 'D:/';
var stringToSearch = 'test';
var promises = [ ];
var traverseWait = 0;
var onTraverseComplete = function() {
Q.allSettled(promises).then(function(){
console.log('Task is completed');
});
}
var waitForTraverse = function(){
if(traverseWait){
clearTimeout(traverseWait);
}
traverseWait = setTimeout(onTraverseComplete, 5000);
}
var scan = function(dir) {
fs.readdir(dir, function(err, files) {
files.forEach(function (file) {
var abPath = dir + '/' + file;
var future = Q.defer();
try {
fs.lstat(abPath, function(err, stat) {
if(!err && stat.isDirectory()) {
scan(abPath);
}
});
}
catch (e) {
console.log(abPath);
console.log(e);
}
matchString(file,abPath);
future.resolve(abPath);
promises.push(future);
waitForTraverse();
});
});
}
var matchString = function (fileName, fullPath) {
if(fileName.indexOf(stringToSearch) != -1) {
console.log(fullPath);
}
}
scan(dirToScan);
}
searchApp();

Node js - Wierd variable scope

Here's the code I use to browse a directory :
var path = 'D:/Syslog/live';
listDir(path);
function listDir (path) {
fs.readdir(path, function(err, files)
{
console.log(files);
for( i = 0; i < files.length; i++)
{
var fullPath = path + "/" + files[i];
fs.stat(fullPath, function(err, stats){
if (stats.isDirectory())
{
listDir(fullPath);
} else
{
console.log(files[i]);
}
});
}
});
}
When I debug and use the variable fullPath it works fine, if I use files[i] (which is declared in the level, i is undefined
As it's an asynchronous loop, i is iterating much faster than the rest of the code. You can use an anonymous closure function to freeze i within the loop.
Have a look at closures.
The popular async library is good for this sort of stuff too.
function listDir(path) {
fs.readdir(path, function(err, files) {
console.log(files);
for (i = 0; i < files.length; i++) {
(function(i) {
var fullPath = path + "/" + files[i];
fs.stat(fullPath, function(err, stats) {
if (stats.isDirectory()) {
listDir(fullPath);
} else {
console.log(files[i]);
}
});
})(i);
}
});
}
If you were using the async library, it'd look similar to this
var async = require('async');
function listDir(path) {
fs.readdir(path, function(err, files) {
console.log(files);
async.each(files, function(file, callback) {
var fullPath = path + "/" + file;
fs.stat(fullPath, function(err, stats) {
if (stats.isDirectory()) {
listDir(fullPath);
} else {
console.log(file);
}
callback();
});
});
});
}
Both tested and working.

Resources