Should I use promise for mkdir - javascript

I use the bluebird magic
var fs = Promise.promisifyAll(require('fs'));
and use
fs.readdirAsync(dest).then(function (val) {
return val;
}).then(function (file) {
...
My question is for the following code (which is working) should I use the same and how
I am talking about the mkdir function.
function createDir(folder) {
return function (req, res, next) {
if (typeof require.cache.per === 'undefined') {
require.cache.per = {};
require.cache.per.mk = false;
}
if (!require.cache.per.mk) {
fs.mkdir(folder, function (e) {
if (!!e && e.code !== 'EEXIST') {
console.log('Error to create folder: ' + err);
}
require.cache.per.mk = true;
next();
});
} else {
next();
}
};
}
My Question is should I use promise here or not, what is recommended ?
The code is working as expected...

A Promise simplifies, and unifies the interface. Either .promisify() or .promisifyAll() will do the trick.
Then you can chain everything like this:
fs.mkdir(dir)
.then(function success(dir) {
...
})
.catch(function failure(err) {
...
})
.finally(function () {
});
However in node.js, the most important thing is to NOT block the I/O. It doesn't matter whether you use a Promise or a regular async/callback, as long as it's not blocking the main thread.
It's ok to have synchronous code in script that you want to run in shell, but for regular applications you should never use blocking I/O operations on purpose.

I would definitely update your code to be consistent. If possible, call mkdirAsync instead of mkdir
Example (from OP's code):
var fs = Promise.promisifyAll(require('fs'));
// ...
fs.mkdirAsync(folder)
.catch({ code: 'EEXIST' }, function(e){
// don't care about this error code
})
.catch(function(e) {
console.log('Error to create folder: ' + e);
})
.then(function(){
require.cache.per.mk = true;
next();
});

Promise.promisifyAll(fs);
return fs.mkdirAsync(dir1)
.then(function() {
return fs.mkdirAsync(dir2);
})
.then(function() {
return fs.mkdirAsync(dir3);
})
Hope this helps.

Related

how do I exit (return) from a function inside a another function

i made this to save a some info on a file and to read line by line using readline node module
there is two res.send() one is with return . it only return within current function its sitting on . How do i completely exit from then functions?
this just for a test . I know I should use Databases
router.post('/login', (req, res) => {
console.log(req.body);
var lineReader = require('readline').createInterface({
input: require('fs').createReadStream('./users.txt')
});
lineReader.on('line', function (line) {
const lineJson = JSON.parse(line);
if (lineJson["username"] == req.body.username) {
if (lineJson["password"] == req.body.password) {
return res.send({ msg: "matched" });
}
}
})
res.send({msg:"not matched"});
})
simplified
function(){
function(){
return...
}
}
Your problem is related to your experience with the asynchronous nature of nodejs.
You need to use the line-reader in async mode for your tests:
lineReader.eachLine('file.txt', function(line, last, cb) {
console.log(line);
if (/* done */) {
cb(false); // stop reading
} else {
cb();
}
});
Or just read the entire file and then query it as if it was a sql table:
var table = //some asyn read of file
if(user-password match){
return res.send({ msg: "matched" });
}else{
return res.send({msg:"not matched"});
}
You can also read the file in async mode (which is better) and in the callback execute your express logic

ES6 generator functions in angular

recently I started using generators in my angular project. Here's how I do it so far:
function loadPosts(skip) {
return $rootScope.spawn(function *() {
try {
let promise = yield User.findAll();
$timeout(function () {
// handle the user list
});
} catch (err) {
// handle err
}
});
}
From what I've read the next part won't be necessary in es7, but currently I have the spawn function in the run block of my app.
$rootScope.spawn = function (generatorFunc) {
function continuer(verb, arg) {
var result;
try {
result = generator[verb](arg);
} catch (err) {
return Promise.reject(err);
}
if (result.done) {
return result.value;
} else {
return Promise.resolve(result.value).then(onFulfilled, onRejected);
}
}
var generator = generatorFunc();
var onFulfilled = continuer.bind(continuer, "next");
var onRejected = continuer.bind(continuer, "throw");
return onFulfilled();
};
Everything works find the way I do it at the moment, the only thing I really don't like is that I have to call $timeout() after each promise. If I don't my $scope variables initialized inside the timeout won't be initialized. It seems to me that angular digest system needs to be triggered manually.
Why is that and is there a way to make this cleaner?
I would assume it is because your spawn method uses native Promises, not the angular implementation. Try to use $q instead:
function continuer(verb, arg) {
var result;
try {
result = generator[verb](arg);
} catch (err) {
return $q.reject(err);
}
if (result.done) {
return result.value;
} else {
return $q.resolve(result.value).then(onFulfilled, onRejected);
}
}

Promise then is called before the before the previous then was finished

I've node app with the following code:
When I run the node app the console.log("after start") is called before
the start was finished, I need it to be after the start will finished,
what am I doing wrong here?
myprocess.start(function() {
//this is called before the start was finished.
console.log("After start");
server.listen(app.get('port'), function(err) {
if (err) {
console.error(err);
} else {
console.log(' listen to: ' + app.get('port'));
}
});
});
the file myprocess.js contain the following
exports.start = function (callback) {
Validator.validateJson(function (err) {
console.log(err);
process.exit(1);
});
plugin.parse().then(function (configObj) {
if (typeof require.cache.persist === 'undefined') {
require.cache.persist = {};
}
require.cache.persist.configObj = configObj;
}, function (err) {
console.log(err);
});
var run= function () {
return Promise.all([
childPro.create(path.join(value)),
childPro.findAndUpdateUser()
]).spread(function (cmd,updatppEnv) {
return Promise.all([childProc.executeChildProcess('exec', cmd, updatedAppEnv), Promise.delay(50).then(function (results) {
return inter.ProcessRun(val);
})]);
})
}();
//I want that this callback will be called after the run promise will be finished
run.then(callback());
}
How can I make the server code runs after all the start process will be finished ?
UPDATE
For me its sufficient to wait until the inter.ProcessRun(val); is resolved to call to the callback how it can be done?
You are immediately invoking callback by doing run.then(callback()). you want run.then(callback).
I guess you forgot a return statement.
Try
return run.then(callback);

Testing async waterfall with mocha seems to stall

I'm trying to add some mocha testing to a node module I have, but I'm new to it, and my lack of concreteness in terms of callbacks is hampering me.
I have tried to pare things back to the most straightforward example, but it's still not working.
So my main.js is
var async = require('async');
var myObject = {};
myObject.test = function(params) {
async.waterfall([
async.apply(test, params)
],
function(err, result){
if (err) {
console.log('Error: ' + err);
} else {
if (result === 200) {
return result;
}
}
});
};
function test(params, callback) {
if(params) {
callback(null, 200);
}
}
module.exports = myObject;
Then my test file
var assert = require("assert");
var myObject = require('./main');
describe('test', function(){
it("should return 200", function(done){
myObject.test({test: 'such test'}, function(err, res) {
if (err) return done(err);
assert.equal(res, 200);
done(res);
});
})
});
If I just run mocha it times out so I'm suspicious about that! Trying mocha --timeout 15000 also just stalls. Any direction you can provide would be really appreciated!
I got this far using this answer but can't get any further.
OK, I think I sorted it, but would still appreciate some feedback to see if I'm approaching it correctly, rather than just managing to get my test to pass.
var async = require('async');
var myObject = {};
myObject.test = function(params, callback) {
async.waterfall([
async.apply(test, params)
],
function(err, result){
if (err) {
console.log('Error: ' + err);
} else {
if (result === 200) {
callback(result);
}
}
});
};
function test(params, callback) {
if(params) {
callback(null, 200);
}
}
module.exports = myObject;
and the test file is
var assert = require("assert");
var myObject = require('./main');
describe('test', function(){
it("should return 200", function(done){
myObject.test({test: 'such test'}, function(res) {
assert.equal(res, 200);
done();
});
})
});
You fixed your main issue but your code still is broken. When you have an async method that takes a callback, you must always invoke the callback exactly once in all cases or your program's control flow will break. If you write an if/else clause, both branches must invoke the callback function. Both of your if statements above violate the callback contract. Check out understanding error-first-callbacks from The Node Way for a good explanation.

What's the best way to get a function return to wait until an asynchronous operation has finished?

Given the following prototype function:
Client.prototype.getLocalIp = function() {
var rtc = new window.RTCPeerConnection({iceServers: []});
rtc.createDataChannel('', {reliable: false});
var that = this;
rtc.onicecandidate = function(event) {
if (event.candidate) {
that.localIp = grep(event.candidate.candidate);
}
};
rtc.createOffer(function (offer) {
that.localIp = grep(offer.sdp);
rtc.setLocalDescription(offer);
}, function (error) {
console.warn('Fetching local IP failed', error);
});
var grep = function(sdpOrCandidate) {
// Does lots of string processing stuff and returns a string
}
console.log("Returning from function");
console.log(this.localIp);
}
How can I stop the function from returning until the grep function has finished doing its business and returned a value? Here's a JSFiddle demonstrating what I mean: http://jsfiddle.net/tjkxcL1j/
If you look in your browser console you should see that the getLocalIp() function is returning null first until the async stuff from rtc.onicecandidate and/or rtc.createOffer is finished.
Your function needs to accept a callback argument
Client.prototype.getLocalIp = function getLocalIp(done) {
// ...
rtc.createOffer(function (offer) {
that.localIp = grep(offer.sdp);
rtc.setLocalDescription(offer);
// call the callback here
done(null, that.localIp);
},
function (error) {
console.warn('Fetching local IP failed', error);
// call the callback with an error here
done(error);
});
};
Then you can use it like this
client.getLocalIp(function(err, ip){
if (err) return console.error(err.message);
console.log("client ip", ip);
});
However, as #zerkms mentions in a comment, this is only going to work if actually async operations are happening. Examples include accessing information over a network or accessing the disk.

Categories

Resources