javascript - 在 node.js 中引发错误

标签 javascript node.js error-handling

我有一个小模块,可以作为我的数据模型。它位于我的路线和特定数据(在我的情况下为用户数据)的数据库之间。

我在我的路由代码中需要这个模块,调用它的 subscribe 方法,并通过将所需数据存储在我的数据库中来为用户订阅特定的邮件列表。耶!

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

如何抛出错误并指向具有不正确 id 的行号?

model/user.js 内部的代码:

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

route.js 内部的代码:

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

现在,我得到:

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

最佳答案

如果您使用 Node 式回调,convention 不是throw。而是将错误作为第一个参数传递给回调 -

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

使用回调是一种愚蠢的函数,因为它可以以纯同步方式编写,但希望这能说明这种模式


你的函数可能已经以同步方式编写了——别担心,我们可以使用下面的 cps2 将它转换为 Node 样式的回调函数 -

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


综上所述,现在大多数人都在使用 Promises。下面我们演示如何将 Node 样式的回调函数转换为返回 Promise 的回调函数。注意,nodeutil.promisify 的形式提供了这个函数,虽然我在这里实现它是为了演示 -

// 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 只是函数,所以你可以用任何你喜欢的方式编写这种东西——不要认为你必须使用 Node 样式的“回调”或 Promise,因为这是你见过的唯一方式-

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

关于javascript - 在 node.js 中引发错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33086247/

相关文章:

javascript - 我如何使用循环在 JavaScript 中声明动态变量?

javascript - 将 CURL 命令转换为 NPM 请求调用

node.js - 找不到 bundle.js [Webpack]

php - 如何更改PHPUnit错误消息以显示自定义错误

node.js - 类型错误 : past must be a string or Buffer

javascript - 使用 JavaScript 计算两个日期之间的周数

javascript - 使用其他 javascript 代码在 javascript 代码中定义字体

javascript - dojo contentPane,我在我的 ContentPane 中发布带有 href 的 html 代码。 html代码有脚本但不起作用,为什么?

javascript - 如何使用 OAuth2 在客户端 angularjs 应用程序中存储 clientId 和 clientSecret?

error-handling - 如果不使用返回值, `unwrap()` 的用途是什么?