nodejs arrow function not returning expected value - node.js

I'm using the aws-sdk to upload a message to kinesis. It works fine but i'm trying to solve for when the action does not work (due to internet being down or something).
Here is the code i'm running.
const returnValue = kinesis.putRecord(params, (err, data) => {
if (err) {
logger.info(err);
return err;
} else {
logger.info(data);
return data;
}
});
console.log(returnValue);
I expect to get back the err or data. Instead what I get back is a Huge json of what I assume is the kinesis.PutRecord request itself.
Any ideas on why i'm not getting data returned to my returValue variable?
The console logs data and error just fine.
UPDATE:
as pointed out in the comments, I needed to wrap the function in a promise. I also put it in a try catch since if you throw a "reject" without a catch you get an unhandled promise rejection.
Updated code here:
try {
const returnValue = await new Promise(function(resolve, reject){
kinesis.putRecord(params, (err, data) => {
if (err) {
logger.info(err);
reject(err);
} else {
logger.info(data);
resolve(data);
}
});
});
logger.log(returnValue);
} catch (error) {
logger.error(error);
return error;
}

Related

Where should the callback be in fs.writefile?

I am a beginner to node.js and I have been following an online course when I received this error: TypeError [ERR_INVALID_CALLBACK]: Callback must be a function. Received undefined
fs.writeFile(fileDescriptor, function (err) {
if (!err) {
fs.close(fileDescriptor, function (err) {
if (!err) {
callback('false');
} else {
callback('Error closing existing file');
}
});
} else {
callback('Error writing to existing file');
}
});
I am pretty sure that I have already included a callback here. How should I solve this?
You are not providing a callback function to fs.writeFile (should be the third argument) and the second argument for fs.writeFile should be the data which you want to write.
const fs = require('fs');
const data = "Text, text and more text.";
function callback(err) {
if (err)
console.log(err);
else {
console.log("File written successfully\n");
}
}
fs.writeFile("file.txt", data, callback);
More info:
callbacks: https://codeburst.io/javascript-what-the-heck-is-a-callback-aba4da2deced
fs.writeFile: https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fswritefilefile-data-options-callback

Node Js call back / promise/ return

I am kind of new to this node js and went through many explanations, tried many solutions but still cant get my head wrapped around the function call backs.
//app.js file
var dashboardfunc = require('./models/admindashboard');
app.get("/dashboard/:id?", function(req, res) {
console.log("we are here in dashboard")
var data = {id: req.params.id};
console.log(data)
dashboardfunc.productlist().then(function(results){
console.log("i am here now ....")
console.log(results)
}).catch(function(err){
if(err){
console.log(err)
}
})
});
//admindashboard.js file
//I tried many other alterations like using call back etc.
// i want the damn results to be back to the app.js and use that
//
function productlist(data) {
return new Promise(function(resolve, reject) {
var param = [data.id];
var sql = 'select * from product where seller_id=?';
console.log(param)
pool.query(sql, param, function(err, results) {
if (err) {
console.log(err)
}
else {
if (results === undefined) {
reject(new Error("Error rows is undefined"));
}
else {
console.log("we got here in productlist")
console.log(results)
return results;
}
}
})
})
}
module.exports = productlist;
<--Result -->
Rb-v2 started !!!
we are here in dashboard
{ id: '23' }
TypeError: dashboardfunc.productlist is not a function
Question is why it is so hard to get the results back , and why it needs to be so complicated to call a function , get the return data. Along with that whats the deal with callback v/s promise ( yeah I read almost all post in it still my naive brain cant process it)
Try these small fixes for the start:
admindashboard.js exports the only function, but app.js tries to use it as a property of an object. You need either this type of export:
module.exports = { productlist };
or this using:
dashboardfunc().then
The argument in the imported function call is missing. Try dashboardfunc(data).then instead of mentioned dashboardfunc.productlist().then.
resolve callback is not used in productlist() function. Use it to return the data from the promise: resolve(results); instead of return results;.
Be consistent in error handling. Use:
if (err) {
reject(err)
}
else {
if (results === undefined) {
reject(new Error("Error rows is undefined"));
}
instead of:
if (err) {
console.log(err)
}
else {
if (results === undefined) {
reject(new Error("Error rows is undefined"));
}

Nodejs - Cannot read property then of undefined

I'm getting this error when executing the following code:
getAggregatedRatings(query).then(ratings=>{
if(ratings){
return res.json(ratings);
}else{
return res.send(200);
}
}).catch((error)=>{
return res.send(500);
});
function getAggregatedRatings(query){
movieRating.aggregate(query)
.exec((err, ratings)=> {
if (err || !ratings) {
return Promise.reject(err);
}
else {
return Promise.resolve(ratings);
}
});
}
Please note that 'getAggregatedRatings' returns the query results as expected.
Please advise what I'm doing wrong.
Your getAggregatedRatings function is not returning a promise, or anything for that matter, which explains why when trying to access it, the result is undefined.
Try changing it to this:
function getAggregatedRatings(query){
return new Promise((resolve, reject) => {
movieRating.aggregate(query)
.exec((err, ratings)=> {
if (err || !ratings) {
reject(err);
}
else {
resolve(ratings);
}
});
})
}
It appears you may be using mongoose for this query. If you're using a recent version of mongoose, then .exec() already returns a promise so you can avoid the promise anti-pattern of wrapping one promise in a manually created new promise whereas you can instead just use the promise it already returns:
function getAggregatedRatings(query){
return movieRating.aggregate(query).exec().then(result => {
if (!result) {
throw new Error("no results found");
}
});
}

NodeJS: understanding promise

I am starting to use promise in NodeJS. The requirement is to use these because of async calls. Here is the first code I wrote for promise.
function asyncFunc(data) {
return new Promise(
function(resolve, reject) {
try {
resolve(data);
} catch (err) {
reject("Custom Error");
}
});
}
//Usage:
asyncFunc('Sample String')
.then(result => { console.log(result); })
.catch(error => { console.log(error); });
//Output:
Sample String
null
//If I change the code to:
function asyncFunc(data) {
return new Promise(
function(resolve, reject) {
try {
reject("Custom Error");
} catch (err) {
resolve("Data");
}
});
}
//Output:
//Exception has occurred: string
//I get the above exception at line: reject("Custom Error");
So the question is "reject" can only be used from "catch" block? Why can't I raise "reject" event manually? What is the scenario "reject" is used? Can someone provide me a better example where I can use both "resolve" and "reject"?
You can use reject if you want, of course.
Let's suppose you have a function that resolves a promise if a person is adult, and rejects it if not.
You'd have something like this:
function asyncFunc(age) {
return new Promise((resolve, reject) => {
if(age >= 18) {
resolve(true);
} else {
// here you call reject manually outside of a catch block
reject(false);
// or
// reject(Error('not adult'));
}
});
}
usage:
asyncFunc(19).then(result => {
console.log(result); // true
})
.catch(error => {
console.log(error); // false or Error('not adult')
});
Probably you got something like (node:5009) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Looks like you run your asyncFunc(..) in console. In this case node.js first execute your function after your hit Enter. Try to take your code to curly brackets like this:
{
asyncFunc('Sample String')
.then(result => { console.log(result); })
.catch(error => { console.log(error); });
}
In case of a try/catch block you usually reject at catch but you can also reject in try.
resolve and reject are basically callbacks for Promise. if you resolve it will got to the next chain if you reject it will break the chain.
So should use reject when an error occurs cause reject will break the promise chain.
For example.
Lets say you have a function that works with callback and you want to wrap it in a Promise like function. This function will check if user exists in database. If the User is found it will return true if not false and if there is an error in database (eg connection) it will reject.
function checkUserExist(id) {
return new Promise((resolve, reject) => {
checkUserExistInDatabase(id, function(result, error) {
if (error) {
reject(error);
}
if (result != null) {
resolve(true);
} else {
resolve(false);
}
})
});
}
function databaseError() {
return new Promise((resolve, reject) => {
reject();
})
}
var idsThatExist = [];
checkUserExist(1).then(function(exist) {
if (exist)
idsThatExist.push(1);
return checkUserExist(2)
}).then(function(exist) {
if (exist)
idsThatExist.push(2);
return databaseError(3)
}).then(function(exist) {
//WILL never Reach here
if (exist)
idsThatExist.push(3);
return checkUserExist(4)
}).then(function(exist) {
if (exist)
idsThatExist.push(4);
}).catch(function(err) {
//it will skip checkUserExist(4)
console.log('I got rejected after checked users:'
idsThatExist)
})
So the question is "reject" can only be used from "catch" block?
No, You can use reject anywhere. Catch isn't necessary to use reject
Why can't I raise "reject" event manually?
You can reject using creating new Promise() or static methods of Promise . See promiseUsingNew() and promiseUsingStaticMethod()
What is the scenario "reject" is used?
try/catch is used for error handling in synchronous programming. resolve & reject is for error handling in asynchronous programming operation instead of callbacks.
Can someone provide me a better example where I can use both "resolve" and "reject"?
'use strict';
function promiseUsingNew(marks) {
return new Promise((resolve, reject) => {
if (marks < 0 || marks > 100) {
return reject('Invalid marks');
}
if (marks >= 40) {
return resolve('You passed');
} else {
return resolve('You Failed');
}
});
}
function promiseUsingStaticMethod(marks) {
if (marks < 0 || marks > 100) {
return Promise.reject('Invalid marks');
}
if (marks >= 40) {
return Promise.resolve('You passed');
} else {
return Promise.resolve('You Failed');
}
}
// you can use promiseUsingNew(marks) or promiseUsingStaticMethod(marks)
promiseUsingNew(221).then((result) => {
console.log(result);
}).catch((error) => {
console.log(error);
});

stop promise chain with multiple catches

In Node.js, I need to read a file and validate it's contents, all in async. I m using Node.js 6.6, bluebird 3.4.6
Example code:
// pseudo function to read file contents - resolves when 'flag' is true, rejects when 'flag' is false.
function readFile(flag) {
return new Promise(function (resolve, reject) {
console.log('Reading file...');
if (flag) {
resolve('File contents');
} else {
reject('readFile error');
}
});
}
// pseudo function to validate file contents - resolves when 'flag' is true, rejects when 'flag' is false.
function validate(fileContents, flag) {
return new Promise(function (resolve, reject) {
console.log('Validating file: ', fileContents);
if (flag) {
resolve('Validate passed');
} else {
reject('validation failed');
}
});
}
readFile(false)
.then(function (fileContents) {
console.log('Successfully read the file:', fileContents);
return fileContents;
})
.catch(function (fileReadErr) {
console.log('Failed to read the file:', fileReadErr);
throw fileReadErr; // or, return Promise.reject(err);
})
.then(function (fileContents) {
return validate(fileContents, false);
})
.then(function (result) {
console.log('Successfully validated the file:', result);
})
.catch(function (err) {
console.log('Failed to validate the file:', err);
})
;
<script src="https://cdn.jsdelivr.net/bluebird/3.4.6/bluebird.min.js"></script>
The above code will print
Reading file...
Failed to read the file: readFile error
Failed to validate the file: readFile error
The above promise chain roughly translates to below sync code:
try {
let fileContents;
try {
fileContents = readFile(false);
console.log('Successfully read the file:', fileContents);
} catch (e) {
console.log('Failed to read the file:', e);
throw e;
}
let validationResult = validate(fileContents, false);
console.log('Successfully validated the file:', validationResult);
} catch (err) {
console.log('Failed to validate the file:', err);
}
And, throwing or rejecting in the first catch method will still invoke the 2nd catch method.
My question: Is there any way to break the chain once the file reading is failed? My objective is to return different HTTP status codes (file read error: 500, validation failed: 400) from an express.js route.
I know a solution using non-standard specialized catch method, but that requires special handling. In the sense, I need to throw errors or need some filtering key in the error object and both of which are not in my hands, and involves some work to achieve it. This solution is mentioned in bluebird docs & here: Handling multiple catches in promise chain
The simplest solution by far is to use what I call "insulated catches". ie, a pattern in which each .catch() is a specialist, associated with a particular step in the overall process, and the main chain comprises only .thens (and eventually a single, terminal catch).
Also, it is useful in this kind of circumstance to convey added information down the error path by re-throwing Error objects with added properties. This avoids the need for custom Errors.
Promise.resolve()
.then(function() {
return readFile(false)
.then(function (fileContents) {
console.log('Successfully read the file:', fileContents);
return fileContents;
})
.catch(function (error) {
error.code = 521; // or whatever
error.customMessage = 'Failed to read the file';
throw error;
})
})
.then(function (fileContents) {
return validate(fileContents, false)
.then(function (result) {
console.log('Successfully validated the file:', result);
return fileContents;
})
.catch(function (error) {
error.code = 522; // or whatever
error.customMessage = 'Failed to validate the file';
throw error;
});
})
.catch(function(error) { // terminal catch.
console.log(error);
// It's possible for unaugmented errors to reach this point,
// so be sure to test for the extra properties before trying to use them.
if(error.code) {...}
if(error.customMessage) {...}
// Note also that the original error.message is still intact.
});
The initial Promise.resolve() isn't strictly necessary, but helps keep everything else symetrical.
This will work with any Promises/A+ lib. Bluebird-sugar is not required.
You can create custom Error types like so:
ReadFileError = function() {};
ReadFileError.prototype = Error.prototype;
ValidationError = function() {};
ValidationError.prototype = Error.prototype;
Then, you can throw from a Promise instead of rejecting:
function validate(fileContents, flag) {
return new Promise(function (resolve, reject) {
console.log('Validating file: ', fileContents);
if (flag) {
resolve('Validate passed');
} else {
throw new ReadFileError('readFile error');
}
});
}
Then you can catch different errors based on their types:
readFile(false)
.then(function (fileContents) {
console.log('Successfully read the file:', fileContents);
return fileContents;
})
.then(function (fileContents) {
return validate(fileContents, false);
})
.then(function (result) {
console.log('Successfully validated the file:', result);
})
.catch(ReadFileError, function (err) {
console.log(..., err);
})
.catch(ValidationError, function (err) {
console.log(..., err);
})
catch(function(err) {
...
});
Maybe more people could get the same problem. I personally don't think this is the best way to do this, because then you have your app throwing pseudo error, which could mistakenly be processed by other error processing on your server. But it works like you proposed:
// pseudo function to read file contents - resolves when 'flag' is true, rejects when 'flag' is false.
function readFile(flag) {
return new Promise(function (resolve, reject) {
console.log('Reading file...');
if (flag) {
resolve('File contents');
} else {
throw new Error ('errorReading');
}
});
}
// pseudo function to validate file contents - resolves when 'flag' is true, rejects when 'flag' is false.
function validate(fileContents, flag) {
return new Promise(function (resolve, reject) {
console.log('Validating file: ', fileContents);
if (flag) {
resolve('Validate passed');
} else {
throw new Error ('validationFailed');
}
});
}
readFile(false)
.then(function (fileContents) {
console.log('Successfully read the file:', fileContents);
return fileContents;
})
.then(function (fileContents) {
return validate(fileContents, false);
})
.then(function (result) {
console.log('Successfully validated the file:', result);
})
.catch((error) => {
console.log(error.name);
console.log(error.message);
if (error.message === 'errorReading'){
console.log('error 500 - File could\'d be read');
// Maybe more custom error processing here
//return res.status(500).send(JSON.stringify({
// 'status' : 'error',
// 'message' : 'File could\'d be read'
//}));
} else if (error.message=== 'validationFailed'){
console.log('error 500 - Validation not OK');
// Maybe more custom error processing here
//return res.status(500).send(JSON.stringify({
// 'status' : 'error',
// 'message' : 'Validation not OK'
//}));
} else {
console.log('error 500 - Some really bad stuff!');
//return res.status(500).send(JSON.stringify({
// 'status' : 'error',
// 'message' : 'Some really bad stuff!',
// 'errorMessage': error
//}));
}
});
<script src="https://cdn.jsdelivr.net/bluebird/3.4.6/bluebird.min.js"></script>
Please note that I commented out the res.send of express to avoid errors on the processing of this snippet!
As far as i understand what you want to achieve i would suggest always using one single catch block (when can be avoided introducing nesting in promise logic which is totally ok in few use cases, but should be avoided when it can be, because you will potentially ends up with promise hell with indentation all around)
Can you handle all errors in your functions readFile, validate in uniform way like:
const error = new Error('something bad happened')
error.status = 500
return reject(error)
Then you could do you handle error logic within one single catch block based on status such as res.status(err.status || 500).json(...)

Resources