简体   繁体   中英

Throwing an error in node.js

I've got a tiny module that acts as a model for my data. It sits between my routes and my database for particular data (user data in my case).

I require this module in my route code, call the subscribe method that it has, and that subscribes a user to a particular mailing list, by storing the needed data in my database. Yay!

My 'subscribe' method accepts an email and an email list ID as the two parameters. It's reasonable that I'll code sloppy and fast and put in an id for a list that doesn't exist. Spelling error, you name it.

How can I throw an error and point to the line number with that incorrect id?

Code from inside model/user.js:

if (emailLists.indexOf(listId) === -1) {
  throw new Error('listId does not exist');
}

Code from inside route.js:

user.subscribe('fake@email.com', 'knewsletterr', function (error, success) {
  if (error) { return sendResponse(500, 'Ahhhhhhh!'); }
  if (!error) { return sendResponse(200, 'subscribed'); }
});

Right now, I'm getting:

/home/.../project/models/user.js:85
if (emailLists.indexOf(listId) === -1) { throw new Error('listId does not exist'); }
                                                   ^
Error: listId does not exist

If you're using node-style callbacks, the convention is not to throw . Instead pass you error as the first argument to your callback -

 // divide with callback function div (x, y, done) { if (y === 0) return done (Error ('Cannot divide by zero')) else return done (null, x / y) } div (6, 3, function (err, result) { // *always* check for err if (err) console.log ('error', err.message, err.stack) else console.log ('result', result) })

Kind of a stupid function to use a callback since it can be written in a purely synchronous way, but hopefully this illustrates the pattern


Your function might already be written in a synchronous way – don't worry tho, we can convert it to a node-style callback function using something like cps2 below -

 // a "normal" synchronous function that throws an error const div = (x, y) => { if (y === 0) throw Error ('cannot divide by zero') else return x / y } // convert it to a continuation passing style (cps) function const cps2 = (f, x, y, k) => { try { return k (null, f (x, y)) } catch (err) { return k (err) } } // logging utility for demos below const logger = (err, result) => { if (err) console.log ('error:', err.message, err.stack) else console.log ('result:', result) } cps2 (div, 6, 3, logger) // result: 2 cps2 (div, 6, 0, logger) // error: cannot divide by zero


All of that said, most peoples are using Promises nowadays. Below we demonstrate how to turn a node-style callback function into one that returns a Promise. Note, node provides this function as util.promisify , though I've implemented it here for demonstration purposes -

 // a conventional function with a node-style callback const div = (x, y, done) => { if (y === 0) return done (Error ('cannot divide by zero')) else return done (null, x / y) } // convert a node-style callback function to a promise-returning function const promisify = f => (...args) => new Promise ( (resolve, reject) => f ( ...args , (err, result) => err ? reject (err) : resolve (result) ) ) // logging utility for demos below const logger = p => p .then (console.log, console.error) logger (promisify (div) (6, 3)) // 2 logger (promisify (div) (6, 0)) // Error: cannot divide by zero


Continuations are just functions tho so you can write this kind of thing in any way that you like – don't think you have to use node-style "callbacks" or Promises just because that's the only way you've seen it -

 const cont = (...values) => k => k (...values) const div = (x, y) => y === 0 ? cont (Error ('cannot divide by zero')) : cont (null, x / y) const logger = (err, result) => err ? console .log ('error:', err.message) : console .log ('result:', result) div (6, 3) (logger) // result: 2 div (6, 0) (logger) // error: cannot divide by zero

This will help you !

 var el = document.getElementById('el'); var log = function( val ){ el.innerHTML+= '<div><pre>' + val + '</pre></div>'; }; try { throw Error('error in code'); } catch (e) { log( e.message ); log( e.fileName ); log( e.lineNumber ); log( e.stack ); };
 <div id='el'></div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM