NodeJS return not stopping the entire function - node.js

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

Related

difference between Callback function and Promise and Async awit

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

Why my lambda is working only when i give a callback with some message?

I am trying to run a small snippet of lambda code where i am pushing data to S3 using firehose. Here is my snippet
const AWS = require( 'aws-sdk' );
var FIREhose = new AWS.Firehose();
exports.handler = async (event,context,callback) => {
// TODO implement
const response = {
statusCode:200,
Name:event.Name,
Value:event.Value
};
const params = {
DeliveryStreamName: 'kinesis-firehose',
Record: { Data: new Buffer(JSON.stringify(response)) }
};
FIREhose.putRecord(params, (err, data) => {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data);
});
};
Here are my events
{
"Name": "Mike",
"Value": "66"
}
When i run this lambda all i am getting response as null . Since i am not passing any callback lambda will default run the implicit callback and returns null. I see that no data is pushed to S3 bucket.
But when i add callback(null,"success") line at the end like this
FIREhose.putRecord(params, (err, data) => {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data);
});
callback(null,"success")
};
I see the data is pushed to S3. Why is that ?
Does async functions always need a callback with some text appended to it ?
Any help is appreciated ?
Thanks
The problem here is that you're mixing your node.js lambda patterns.
Either you use an asynchronous function and return or throw:
exports.handler = async (event,context,callback) => {
// code goes here.
await FIREhose.putRecord(params).promise();
return null; // or whatever result.
};
Or you use the callback approach:
exports.handler = (event,context,callback) => {
// code goes here.
FIREhose.putRecord(params)
.promise();
.then((data) => {
// do stuff with data.
// n.b. you could have used the cb instead of a promise here too.
callback(null, null); // or whatever result.
});
};
(There's a third way using context. but that's a very legacy way).
This is all due to how lambda works and detects when there's been a response.
In your first example (no callback), lambda is expecting your handler to return a promise that it has to wait to resolve/reject, which, in turn, will be the response. However, you're not returning a promise (undefined) and so there's nothing to wait for and it immediately returns- quite probably before the putRecord call has completed.
When you used callback though, you explicitly told lambda that you're using the "old" way. And the interesting thing about the callback approach is that it waits for node's event loop to complete (by default). Which means that .putRecord will probably complete.

Store database attribute in var

I have the following code:
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database('test.db');
db.serialize(function() {
db.run("CREATE TABLE IF NOT EXISTS counts (key TEXT, value INTEGER)");
db.run("INSERT INTO counts (key, value) VALUES (?, ?)", "counter", 0);
});
var getValue = function(res){
db.get("SELECT value FROM counts", function(err, row){
res.json({ "count" : row.value });
return;
});
};
console.log(getValue);
Output is
[Function]
But should be json. What am I doing wrong?
I took the example from http://dalelane.co.uk/blog/?p=3152
Thanks in advance :)
Of course getValue is a function, because few lines before you wrote:
var getValue = function(res){
// ...
};
so now, when you write:
console.log(getValue);
it tells you that it's a function.
What you probably want is:
getValue({json: console.log});
or maybe:
getValue({json: data => console.log(data.count)});
if you want to display that value from an object passed to res.json, if you have a db.get() function that returns one row in that format - make sure that you're using it correctly in the first place. But keep in mind that this is asynchronous so you won't be able to store it in a variable immediately.
Simplifying your example a little bit, you can do:
asyncFunc('args', function (err, data) {
if (err) {
console.log('Error:', err);
} else {
console.log('Value:', data);
}
});
but you won't be able to return that value, because returning a simple value is a synchronous process. What you can return is a promise:
function getPromise() {
return new Promise(function (resolve, reject) {
asyncFunc('args', function (err, data) {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
that you can then use like this:
getPromise()
.then(value => console.log('Value:', value))
.catch(error => console.log('Error:', error));
If you don't know why is that then you can see some other answers where I explain how to get data from asynchronous function calls which you may find helpful:
A detailed explanation on how to use callbacks and promises
Explanation on how to use promises in complex request handlers
An explanation of what a promise really is, on the example of AJAX requests
An explanation on how to handle errors in callbacks and promises
You did not call the getValue function. Call it like this: getValue(). But that function returns null.
You will need to start with a more basic example. First learn about function calls, then when you have that down move on to other things.

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')

How to return a function from callback?

If I have the following code:
var content;
var f = fs.readFile('./index.html', function read(err, data) {
if (err) {
throw err;
}
content = data;
return console.log(content);
});
f();
I got the following:
f();
^
TypeError: undefined is not a function
How can I do to return a function, which is not undefined?
My real issue, in a bigger context is the following https://gist.github.com/jrm2k6/5962230
You can't usefully return from within the callback to your code.
Using return inside the callback doesn't return a value to your code. fs.readFile() calls the callback itself so the return value is given to it. For your code to receive it, fs.readFile() would have to return the value it got from the callback, which it doesn't.
And, since fs.readFile() is asynchronous, it actually can't. Your code spans 2 different points in time:
"Present"
var content;
var f = fs.readFile('./index.html', /* ... */);
f();
"Future"
/* ... */
function read(err, data) {
if (err) {
throw err;
}
content = data;
return console.log(content);
}
/* ... */
You simply can't use a value from the "Future" in the "Present" -- or, at that point, the "Past."
This all generally leads to continuing the callback pattern rather than using return. Taking your "real" code:
var cheerioURLContent = function (url, callback) {
rest.get(url).on("complete", function (result) {
callback(cheerio.load(result));
});
};
cheerioURLContent('./index.html', function (t) {
console.log(t);
});
You can assign event handlers for custom events and trigger (emit) the events from within the callback. It's a bit hard to get your head around at first, but pretty elegant.
See Emitting event in Node.js for an example.

Resources