Sunday, May 19, 2024
 Popular · Latest · Hot · Upcoming
22
rated 0 times [  28] [ 6]  / answers: 1 / hits: 151999  / 9 Years ago, mon, october 12, 2015, 12:00:00

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('[email protected]', '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

More From » node.js

 Answers
27

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




[#64765] Thursday, October 8, 2015, 9 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
talonb

Total Points: 596
Total Questions: 103
Total Answers: 91

Location: Northern Mariana Islands
Member since Fri, Jan 15, 2021
3 Years ago
;