I'm quite new to Node.js and I'm not sure to completely understand what this error actually means:
process.on('uncaughtException', err => {
^
TypeError: process.on is not a function
I read that one should not import process because it's automatically injected. My code is like this:
var settings;
var jsonfile = require("jsonfile");
var file = "server/settings.json";
try {
var obj = jsonfile.readFileSync(file);
settings = obj;
} catch (err) {
var msg = err + ". Exiting";
console.error(msg);
throw new Error("Fatal");
}
// some other functions
process.on('uncaughtException', function (err) {
console.error((new Date).toUTCString() + ' uncaughtException:', err.message)
console.error(err.stack)
process.exit(1)
})
module.exports.login = login;
module.exports.logout = logout;
My intentions are to exit if I cannot read the settings file. This is by design.
I'm aware other approaches might be better, but my question is why I get the error above?
I'm running Node.js 8.12.0 on Windows 7 64-bit.
if you want to add that, what you can do is use that right at the end of your app.js or server.js( whatever your file may be).
that will globally catch any uncaught errors and log them
app.listen(port, () => console.log(`app listening on port ${port}!`));
process.on('uncaughtException', function (error) {
console.log(error);
});
so exporting is not necessary...
You should move the process.on() function before the try catch, otherwise your uncaughtException event won't take effect.
var settings;
var jsonfile = require("jsonfile");
var file = "server/settings.json";
process.on('uncaughtException', function (err) {
console.error((new Date).toUTCString() + ' uncaughtException:', err.message)
console.error(err.stack)
process.exit(1)
})
try {
var obj = jsonfile.readFileSync(file);
settings = obj;
} catch (err) {
var msg = err + ". Exiting";
console.error(msg);
throw new Error("Fatal");
}
Related
I created a simple custom exception based on this link as follows:
function userErr(message) {
logger.info("reach user error function")
const error = new Error(message);
error.type = "userErr";
return error;
}
function failureErr(message) {
logger.info("reach failure error function")
const error = new Error(message);
error.type = "failureErr";
return error;
}
The expected behaviour is Express will throw this error to the custom error handler middleware at the end of the server.js file:
app.use((error, req, res, next) => {
console.log("Error Handling Middleware: " + error.message);
if (error.type === "userErr") {
res.status(400).json({
status: "error",
statusCode: "400",
message: error.message
});
} else if (error.type === "failureErr") {
res.status(500).json({
status: "fail",
statusCode: "500",
message: error.message
});
} else {
res.status(500).json({
status: "error",
statusCode: "500",
message: error.message
});
}
});
app.listen(8080, () => {
console.log("listening on 8080...");
}); //the server object listens on port 8080
When I put these functions above the routes (app.get, app.post, etc...) in the server.js file (this should be index.js for most people), it works fine. But when I start stripping out these routes and put them into a route file in the routes folder instead, the traffic does come to the route correctly, but whenever an error occurs and executes the function above, JavaScript threw an error at the 2nd line, which is:
const error = new Error(message);
for example:
const error = new Error(message);
^
Error: [object Object]
at new failureErr (file:///.../src/server.js:89:17)
at file:///.../src/routes/testRoutes.js:104:21 {
type: 'failureErr'
Which is weird! I have tried putting these functions into a separate file and importing them into the route file, but it still shows the same error.
I mimicked the folder into the codesandbox (I couldn't manage to make it run) so you can understand the context. The index.js by itself is the one that works, while index2.js with the routers folder is the one that failed.
Appreciate any feedback on the questions, or any ideas on where I did something wrong
The code you show in your sandbox is doing this throw new userError("It's an user error");, but userError() is not properly set up as a constructor and thus can't be called with new. This is the code in your sandbox:
app.get("/api/v1/test", (req, res, next) => {
try {
const userErr = req.headers.userErr;
console.log(userErr);
if (userErr === "true") {
throw new userError("It's an user error");
} else {
throw new failureError("It's an failure error");
}
} catch (e) {
next(e);
}
});
The code you show has not made either userError() or failureError() into classes or constructors. They are merely functions. Therefore, they can't be called with new.
If you want to make them into classes, then do something like this:
class userError extends Error {
constructor(message) {
super(message);
console.log("reach user error function");
this.type = "userErr";
}
}
Note, this is the more modern way of doing this than what is shown in the article you reference (which is apparently old).
Or, you can just use what you have as functions:
app.get("/api/v1/test", (req, res, next) => {
try {
const userErr = req.headers.userErr;
console.log(userErr);
if (userErr === "true") {
next(userError("It's an user error"));
return;
} else {
next(failureError("It's an failure error"));
return;
}
res.send("ok");
} catch (e) {
next(e);
}
});
I'm using mongoose + express to build a simple MERN app.
I need to create multiple documents and save them, but I need to catch all errors.
I'm using this code and it works, but I'd like to handle all errors at once, not repeat the same code multiple times.
If I use try...catch block and remove the callback error handler, I obtain UnhandledPromiseRejectionWarning.
model.save((err, doc) => {
if (err) return console.error(`ERR ${err.message}`);
});
I've tried this:
export const init = async () => {
try {
const newDoc = new MyModel({ test: 'test'});
const savedDoc = await newDoc.save();
console.log('All done :)');
} catch (err) {
console.log('Error');
res.status(400).send(err);
}
}
But I can't catch the error: in debug mode, the program never enter the catch block and I obtain, in case of error for example:
UnhandledPromiseRejectionWarning: MongoError: E11000 duplicate key error collection
Any suggestion?
model.save()
.then(success => {
if(!success) {
// Handle your error
}
// Success
return model2.save();
})
.then(success2 => {
})
// etc..
.catch(err => {
// Handle your error
});
try{
const savedModel = await model.save();
console.log("Model created successfully");
res.status(200).send("Model created successfully");
}catch (err){
console.log(err);
res.status(400).send(err);
}
The code below is a mix of https://www.w3schools.com/nodejs/nodejs_mongodb_find.asp
and
https://stackoverflow.com/questions/49982058/how-to-call-an-async-function#:~:text=Putting%20the%20async%20keyword%20before,a%20promise%20to%20be%20resolved.
When you look at the console.log below the code, things seem to be running out of order. I thought by making the function async and using the .then I would avoid those issues.
I want the MongoDB data retrieval function separate from the app.get function.
No data is being returned to the get request. I guess the app.get code is falling through and ending before the function returns the value. What do I need to correct?
async function getLanguageTranslationData(fromLanguage, toLanguage) {
console.log("Started getLanguageTranslationData")
const databaseUrl = "mongodb://localhost:27017"
const databaseName = 'MyCompanyPOC'
mongoClient.connect(databaseUrl, function(err, conn) {
if (err) throw err;
const collectionName = "Phrases";
var dbo = conn.db(databaseName)
var query =
{ $and:
[ {masterLanguage: fromLanguage},
{localizedLanguage: toLanguage}
]
}
console.log("query=" + JSON.stringify(query));
console.log("about to retrieve data");
dbo.collection(collectionName).find(query).toArray(
function(err, result) {
if (err) throw err;
console.log("Back from mongoDB.find()")
console.log(JSON.stringify(result))
return result
conn.close()
})
})
}
app.get("/api/gettranslations/:fromLanguage/:toLanguage",
async function(req, res) {
console.log("Backend: /api/gettranslations method started: " +
" fromLanguage=" + req.params.fromLanguage +
" toLanguage=" + req.params.toLanguage)
getLanguageTranslationData(
req.params.fromLanguage,
req.params.toLanguage)
.then((arrayResult) => {
console.log("got arrayResult back from getLanguageTranslationData")
res.status(200).json(arrayResult)
console.log("Backend: End of /api/gettranslations process")
})
})
Node.JS Console output:
listening on port 3001
Backend: /api/gettranslations method started: fromLanguage=en-US toLanguage=es-MX
Started getLanguageTranslationData
(node:44572) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
got arrayResult back from getLanguageTranslationData
Backend: End of /api/gettranslations process
query={"$and":[{"masterLanguage":"en-US"},{"localizedLanguage":"es-MX"}]}
about to retrieve data
Back from mongoDB.find()
[{"_id":"5f403f7e5036d7bdb0adcd09","masterLanguage":"en-US","masterPhrase":"Customers","localizedLanguage":"es-MX","localizedPhrase":"Clientes"},{ etc...
The thing is getLanguageTranslationData should return a promise so that you can use it as a promise in your handler, but in your case, call to getLanguageTranslationData will return undefined as all the code inside this function will execute asynchronously due to nodejs non-blocking nature.
So what you can do is return promise from your getLanguageTranslationData function like this.
function getLanguageTranslationData(fromLanguage, toLanguage) {
const databaseUrl = "mongodb://localhost:27017"
const databaseName = 'MyCompanyPOC'
return new Promise((resolve, reject)=>{
mongoClient.connect(databaseUrl, function(err, conn) {
if (err) reject(err);
else{
const collectionName = "Phrases";
var dbo = conn.db(databaseName)
var query =
{ $and:
[ {masterLanguage: fromLanguage},
{localizedLanguage: toLanguage}
]
}
dbo.collection(collectionName).find(query).toArray(
function(err, result) {
if (err) reject(err);
else
resolve(result);
})
}
})
})
}
and then use await in your handler to use that promise returned
app.get("/api/gettranslations/:fromLanguage/:toLanguage",
async function(req, res) {
try{
let arrayResult = await getLanguageTranslationData(req.params.fromLanguage, req.params.toLanguage);
res.status(200).json(arrayResult)
}catch(err){
// return error
}
})
The above code will give you the gist of what you need to do, actual code may vary according to your needs.
You can refer async-await from here
I got it working in this way, based on this example: Node.js, Mongo find and return data
#Namar's answer is probably correct too, but I was testing this the same time he posted. As the StackOverflow question/answer above notes, the up-to-date versions of MongoClient have support for promises. That post also shows how to put in a separate module, which is something I will probably do later this week.
function getLanguageTranslationData(fromLanguage, toLanguage) {
console.log("Started getLanguageTranslationData")
const databaseUrl = "mongodb://localhost:27017"
const databaseName = 'ShedCompanyPOC'
return mongoClient.connect(databaseUrl)
.then(function(conn) {
var collectionName = "UploadedDataeFromExcel";
var dbo = conn.db(databaseName)
var query =
{ $and:
[ {masterLanguage: fromLanguage},
{localizedLanguage: toLanguage}
]
}
console.log("query=" + JSON.stringify(query));
console.log("about to retrieve data");
var collection = dbo.collection(collectionName)
return collection.find(query).toArray();
}).then(function(result) {
console.log("Back from mongoDB.find()")
console.log(JSON.stringify(result))
//conn.close()
return result
});
}
app.get("/api/gettranslations/:fromLanguage/:toLanguage",
async function(req, res) {
console.log("Backend: /api/gettranslations method started: " +
" fromLanguage=" + req.params.fromLanguage +
" toLanguage=" + req.params.toLanguage)
getLanguageTranslationData(
req.params.fromLanguage,
req.params.toLanguage)
.then(function(arrayResult) {
console.log("got arrayResult back from getLanguageTranslationData")
res.status(200).json(arrayResult)
console.log("Backend: End of /api/gettranslations process")
}, function(err) {
console.log("The promise was rejected", err, err.stack)
})
})
In the main process of my Electron app, I'm trying to handle an exception thrown when creating a file that already exists. However, my catch clause is never entered, and the exception is spammed to the user. What am I doing wrong?
let file;
try {
// this line throws *uncaught* exception if file exists - why???
file = fs.createWriteStream('/path/to/existing/file', {flags: 'wx'});
}
catch (err) {
// never gets here - why???
}
The correct way to handle this case is by listening to the error event:
const file = fs.createWriteStream('/path/to/existing/file', {flags: 'wx'});
file.on('error', function(err) {
console.log(err);
file.end();
});
What I've found is:
https://github.com/electron/electron/issues/2479
I tried to replicate with pure Node.js, and it catches errors with process.on('uncaughtException', callback)
let desiredPath = '/mnt/c/hello.txt';
let fs = require('fs');
process.on('uncaughtException', function (error) {
console.log('hello1');
});
try {
fs.createWriteStream(desiredPath, {
flags: 'wx',
});
}
catch (err) {
console.log('hello');
}
//Output is: 'hello1'
I tried it with Ubuntu shell on Windows 10, in my case I don't have permissions to read that file and process.on('uncaughtException', callback) catches it correctly.
I'm trying to establish communication between two node.js scripts.
The first one does a get request and write the response in a file.
The second watch the file after changes, then he read it, and prompt the result.
The first (get then write)
var request = require('request');
var parseString = require('xml2js').parseString;
var fs = require('fs');
//Some needed variables
streamInterval = setInterval(function() {
request.get(addr, function (error, response, body) {
if (!error && response.statusCode == 200) {
parseString(body,{ explicitArray : false, ignoreAttrs : true }, function (err, result) {
var jsonResult = JSON.stringify(result);
var result = JSON.parse(jsonResult);
fs.writeFile(outputDeparts, JSON.stringify(result, null, 4), function(err) {
if(err) {
console.log(err);
}
});
});
}else{
console.log("An error occured : " + response.statusCode);
}
}).auth(LOGIN,PASS,true);
}, 30000);
The second (watch after changes, read and prompt)
var fs = require('fs');
//Some needed variables
fs.watch(outputDeparts, (eventType, filename) => {
console.log(`event type is: ${eventType}`);
if (filename) {
console.log(`filename provided: ${filename}`);
fs.readFile(outputDeparts, 'utf8', function (err, data) {
if (err){
throw err;
}else{
console.log('start parsing');
console.log(data);
var result = JSON.parse(data);
var departs = result["passages"]["train"];
console.log(`next train [${departs[0]["num"]}] at : ${departs[0]["date"]}`);
}
});
} else {
console.log('filename not provided');
}
});
The first time the file is changed everything is ok ! But after 30 second, at the second change I get the following error :
undefined:1
SyntaxError: Unexpected end of input
at Object.parse (native)
at /Users/adobe/Documents/workspace/playWithNode/watchFile.js:17:23
at tryToString (fs.js:414:3)
at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:401:12)
I thought it was a problem with reading/writting a file asynchronously but didn't manage to find a fix...
Is everyone able to help me or having clues ? Thanks
..it isn't encouraged to access the file system asynchronously because, while accessing, the target file can be modified by something in the App Life Cycle.
I suggest you to use fs.readFileSync and to wrap the JSON.parse in a try-catch
var fs = require('fs');
function onNextTrain(data) {
console.log("onNextTrain", data);
return data;
}
fs.watch(outputDeparts, (eventType, filename) => {
return new Promise((resolve, reject) => {
if(!filename) {
return reject("FILE NAME NOT PROVIDED");
}
let
data = fs.readFileSync(filename, 'utf8'),
result
;
try {
result = JSON.parse(data);
} catch(error) {
result = data;
}
return resolve(result);
})
.then(onNextTrain)
.catch(err => console.log("error", err))
;
});
Try change code in second file to
var result;
try {
result = JSON.parse(data);
} catch (err) {
console.error(err, data);
}
because SyntaxError: Unexpected end of input it's JSON.parse error.
In first file I see potential problem in
fs.writeFile(outputDeparts, data, function(err) { ...
Callback function must provide ordered write, but your code - only logged error.
Node.js docs
Note that it is unsafe to use fs.writeFile multiple times on the same file without waiting for the callback. For this scenario, fs.createWriteStream is strongly recommended.