在node.js中抛出错误

时间:2023-01-14 18:29:30

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.

我的“订阅”方法接受电子邮件和电子邮件列表ID作为两个参数。我将编码草率和快速并且为不存在的列表输入id是合理的。拼写错误,你说出来。

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

如何抛出错误并指向具有错误ID的行号?

Code from inside model/user.js:

来自model / user.js内部的代码:

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

Code from inside route.js:

来自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

2 个解决方案

#1


12  

If you're using node-style callbacks, the convention isn't 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

您的函数可能已经以同步方式编写 - 不用担心,我们可以使用类似下面的cps2将它转换为节点式回调函数

// 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

所有这些都说,现在大多数人都在使用Promise

const div = (x, y, done) =>
  {
    if (y === 0)
      return done (Error ('cannot divide by zero'))
    else
      return done (null, x / y)
  }
  
const promisify = f => (...args) =>
  new Promise ((resolve, reject) =>
    f (...args, (err, result) =>
      {
        if (err)
          reject (err)
        else
          resolve (result)
      }))

const logp = p =>
  p.then (console.log, console.error)
  
logp (promisify (div) (6, 3))
// 2

logp (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

Continuations只是函数,所以你可以用你喜欢的任何方式编写这种东西 - 不要认为你必须使用节点式的“回调”或Promise只是因为这是你看到它的唯一方式

const cont = (...values) =>
  k => k (...values)

const div = (x, y) =>
  y === 0
    ? cont (Error ('cannot divide by zero'))
    : cont (null, x / y)

const log = (err, result) =>
  err
    ? console.log ('error:', err.message)
    : console.log ('result:', result)

div (6, 3) (log)
// result: 2

div (6, 0) (log)
// error: cannot divide by zero

#2


2  

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>

#1


12  

If you're using node-style callbacks, the convention isn't 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

您的函数可能已经以同步方式编写 - 不用担心,我们可以使用类似下面的cps2将它转换为节点式回调函数

// 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

所有这些都说,现在大多数人都在使用Promise

const div = (x, y, done) =>
  {
    if (y === 0)
      return done (Error ('cannot divide by zero'))
    else
      return done (null, x / y)
  }
  
const promisify = f => (...args) =>
  new Promise ((resolve, reject) =>
    f (...args, (err, result) =>
      {
        if (err)
          reject (err)
        else
          resolve (result)
      }))

const logp = p =>
  p.then (console.log, console.error)
  
logp (promisify (div) (6, 3))
// 2

logp (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

Continuations只是函数,所以你可以用你喜欢的任何方式编写这种东西 - 不要认为你必须使用节点式的“回调”或Promise只是因为这是你看到它的唯一方式

const cont = (...values) =>
  k => k (...values)

const div = (x, y) =>
  y === 0
    ? cont (Error ('cannot divide by zero'))
    : cont (null, x / y)

const log = (err, result) =>
  err
    ? console.log ('error:', err.message)
    : console.log ('result:', result)

div (6, 3) (log)
// result: 2

div (6, 0) (log)
// error: cannot divide by zero

#2


2  

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>