difference between Callback function and Promise and Async awit - node.js

I Understand Callback Function but I cant understand promise method and async and await.why to use this three function in node js.can give explain for example code.

Callback
Callback is a function that is passed as an argument to another function, and it is executed at the end. Like this:
function(callback){
//you do some tasks here that takes time
callback();
}
The callback is a method to deal with asynchronous code. For example, You may need to read a data form a file in your node app, and this process takes time. So, instead of blocking your code while reading, nodejs execute other tasks and then return back after the callback is executed.
Promise
The promise is also to deal with asynchronous code like callback method does but with more readable way. For example, instead of this:
example(function(){
return example1(function(){
return example2(function(){
return example3(function(){
done()
})
})
})
})
It makes it more readable like this:
example()
.then(example1)
.then(example2)
.then(example3)
.then(done)
Async function / Await
The async function is used to write asynchronous code, specifically promises. inside of this function the keyword await is used to pause the execution of a promise until it is resolved. In other words, it waits for the promise to resolve and then resume the async function. For example:
async function example(){
var data = await getData() // it waits until the promise is resolved
return data;
}

Callback Function
var fs = require('fs');
fs.readFile(fileName, 'utf8', function read(err, contents) {
console.log(contents);
});
console.log('after calling readFile');
Here function read(err, contents){} is a callback function and prints the contents when finished with reading the file.
But the problem in some cases might be is "after calling readFile" gets displayed to console before reading the file.
As Node Js executes statement in asynchronous mode.
Promise
var fs = require('fs');
function readMyFile(fileName)
{
return new Promise(function(resolve,reject)
{
fs.readFile(fileName, 'utf8', function read(err, contents) {
if(err)
reject(err)
else
resolve(contents)
});
}
}
var file = readMyFile(fileName).then(result=>{console.log(result);console.log('after calling readFile'); }).catch(err=>{console.log("Error Occurred",err)});
console.log(file);
Here function readMyFile(fileName) is a function that returns promise prints the contents in then block and displays an error in the catch block.
But here the line console.log(file); gets executed without waiting for the file variable being defined
Async/Await
var fs = require('fs');
function readMyFile(fileName)
{
return new Promise(function(resolve,reject)
{
fs.readFile(fileName, 'utf8', function read(err, contents) {
if(err)
reject(err)
else
resolve(contents)
});
}
}
async function read()
{
var file = await readMyFile(fileName);
console.log(file);
}
Here await hold the line until file variable gets its value
await works only with the promise
await can only be used inside async functions

Related

Return a object from fs.readFile in Nodejs

I am trying to return jsonObj below and it is not returning. Help would be appreciated. Here fileName is the path of the file which I need to read. And again, I need to return jsonObj. So I can access it outside fs.readFile function.``
Here is the code
return fs.readFile(fileName, 'utf-8', (err, fileContent) => {
if(err) {
console.log(err); // Do something to handle the error or just throw it
throw new Error(err);
}
let jsonObj = csvjson.toObject(fileContent);
console.log(jsonObj)
return jsonObj
});
In Node you don't return from a callback function, that gets discarded and ignored. You must either use Promises, possibly in conjunction with async/await, or you must accept a callback function of your own.
This is the founding principle of asynchronous code:
// The fs.readFile() function executes immediately
fs.readFile(..., (err, ...) => {
// This code runs in the distant future, like imagine ten years from now
// from the perspective of the computer.
});
// JavaScript continues here immediately.
The readFile function does not return anything in particular, the inner function has not yet been run. It's also worth noting that throwing exceptions in there is pointless, don't do it.
To chain:
function getData(fileName, cb) {
fs.readFileName(fileName, 'utf-8', (err, fileContent) => {
if (err) {
// Back-propagate the error
return cb(err);
}
// Engage the callback function with the data
cb(null, csvjson.toObject(fileContent));
}
}
Note that this code is a lot less convoluted and messy if you use promises instead.

NodeJS return not stopping the entire function

I have the function, enter, that contains two fs.readFile functions inside and on the innermost readfile I'm checking to see whether a txt file contains a certain keyword, and if it does it should stop the entire enter function.
Her is what the enter function looks like:
async function enter(email, firstName, lastName){
fs.readFile(fileName, function(err, data){
parsedData = JSON.parse(data);
email = parsedData.email;
fs.readFile('./anotherfile.txt', function (err, data) {
if (err) throw err;
if(data.includes(email)){
console.log('Stopping function');
return;
}
});
});
console.log('Continuing with function');
}
The problem is that when anotherfile.txt contains the keyword, it does not stop the entire function, it continues and logs, "Continuing with function" as seen in the code above.
Any help would be appreciated!
fs promises are available Node v11.0.0
or You can can convert like this const readFile = util.promisify(fs.readFile);
const fsp = require('fs').promises;
async function enter(email, firstName, lastName) {
try {
let data = await fsp.readFile(fileName)
let parsedData = JSON.parse(data);
let email = parsedData.email;
data = await fsp.readFile('./anotherfile.txt')
if (data.includes(email)) {
console.log('Stopping function');
return;
}
console.log('Continuing with function');
} catch (err) {
throw err
}
}
This is because of two things.
You are using asynchronous File read, that is, the flow of code won't stop when this readFile is called. Instead, the program would keep executing in a normal fashion. And when the file read operation is completed, the callback function you supplied will be called with the corresponding error or data.
The return statement is inside of the callback function, hence it will only affect that function.
You need to use await when you are dealing with asynchronous functions. Look that up here

object Promise on return

Whenever I'm trying to generate random keys from crypto or nanoid (new library) it just returns [object Promise]
async function createCode(length){
if(!length){
return nanoid;
} else {
return nanoid(length);
}
}
// another one for example
async function createCode(){
return await crypto.randomBytes(64).toString('hex');
}
An async function returns a promise by default. Please call await createCode() in another async function or use createCode().then()
All async function return a promise. Always.
So, the caller of an async function has to either use await themselves (from within another async function) or use .then() to get the value out of the promise.
It doesn't look to me like either of your functions benefit from being async. return await someFunc() when someFunc() returns a promise can be done with just return someFunc() just the same. The await is not necessary at all.
FYI, crypto.randomBytes() uses a callback if you want the asynchronous version. If you don't pass it a callback, then it's just a plain synchronous function. Unless you've done something to make a promisified version of that library, it doesn't return a promise.
So, you can just use this:
// another one for example
function createCode(){
return crypto.randomBytes(64).toString('hex');
}
Which you can just call as a regular function:
let randomVal = createCode();
console.log(randomVal);
If you want the asynchronous version and want to use it with promises, then you'd have to promisify it:
// another one for example
function createCode(){
return new Promise((resolve, reject) => {
crypto.randomBytes(64, function(err, val) {
if (err) return reject(err);
resolve(val.toString('hex'));
});
});
}
Then, you can call it:
createCode().then(val => {
console.log(val);
}).catch(err => {
console.log(err);
});

How to return promise's value, rather than promise itself in await/async?

I have the following code. Basically reading a file then return the content.
var result = await promise; return result;
Right now it returns promise itself. Is it a way to return the result straight away?
FileReader.prototype.readInputFile = async function(fileName) {
var condi = this.validateFileName(fileName);
if(condi == true) {
// wrap api, then wait
var promise = new Promise((res, rej) => {
fs.readFile(fileName, { encoding: 'utf-8' }, (err, data) => {
if(err) {
console.log(err);
rej();
}
res(data);
});
});
var result = await promise;
return result;
} else {
// not valid file
}
}
No you cannot. async function itself returns promise only. No matter what you return(or throw) in the body of function, it will eventually become a Promise.resolve() or Promise.reject().
When you call an async function the result is a promise. You can't expect an async function to return the value synchronously, right? So, the promise's value is returned properly. But the promise you see is the promise of the async function, not the one that was resolved inside it.
Put this console.log between these 2 lines and you would see it's an actual value:
var result = await promise;
console.log(result);
return result;
Now I understand, it will return promise instead, not result. I did find a way that it is able to return result, so the code can be nicely.
FileReader.prototype.readInputFile is an async func. If any non-async func calls it, the result will be promise. If any async func call this acync func. The result is actually data.

how to resolve values in nodejs promises

I am new to promises Q node module.
How to resolve values for promise object.
Here is my example:
function fs_readFile (file, encoding) {
var deferred = Q.defer()
fs.readFile(file, encoding, function (err, data) {
if (err)
deferred.reject(err)
else
deferred.resolve(data)
})
return deferred.promise
}
Now i am calling the function:
var promise=fs_readFile('myfile.txt').then(console.log, console.error);
Now i can get my file content data from then fulfill call back function but how can i get my file content data from returned promises object. like synchronously .
can any one help me!!
Promises help by encapsulating the result of an asynchronous operation but because the operation hasn't finished yet you can't actually get the result synchronously. You can get some of the appearance of synchronous behaviour though. You get the concept of functions taking arguments and returning a value. You also get error handling that climbs the stack in the same way that errors would in synchronous code.
In ES6 (the next version of JavaScript, partially supported by some of the newest browsers) you also get generators which helps you write even more synchronous seeming code.
Consider your readFile operation, if it were synchronous you could write something like:
function readJsonSync(filename) {
return JSON.parse(fs.readFileSync(filename, 'utf8'));
}
with the promise returning version in the current version of JavaScript you could write
function readJson(filename) {
return fs_readFile(filename, 'utf8').then(JSON.parse);
}
If you wanted to do the same with callbacks rathe than promises you'd have to write the following to get proper error handling behaviour:
function readJsonCallback(filename, callback){
fs.readFile(filename, 'utf8', function (err, res){
if (err) return callback(err)
try {
res = JSON.parse(res)
} catch (ex) {
return callback(ex)
}
callback(null, res)
})
}
With ES6 you can write:
var readJson = Q.async(function* (filename){
return JSON.parse(yield fs_readFile(filename, 'utf8'))
})
The yield "awaits" the promise and gives you the resolution value. The caveat is that the function that contains yield must be wrapped in Q.async and will return a promise itself.
If you want a more in depth look at this, or simply prefer videos to text, I gave a talk on this topic that you can find on YouTube: http://youtu.be/qbKWsbJ76-s
function fs_readFile (file, encoding) {
var deferred = Q.defer()
fs.readFile(file, encoding, function (err, data) {
if (err)
deferred.reject(err)
else
deferred.resolve(data)
})
return deferred.promise.then(console.log, console.error)
}
var promise=fs_readFile('myfile.txt','utf-8')

Resources