处理/捕获错误而不重复代码?

时间:2017-10-17 16:17:19

标签: javascript node.js promise

考虑以下(伪)函数来更新数据库:

function my_function(req, res, input) {
  try {
    // This sanitizeInput() function throws error message if input is invalid
    sanitizeInput(input);
  catch (err) {
    res.status(500).json({id:"sql_error",message:err});
    return;
  }

  dbCreateRowPromise(input)
    .then(result => {//Handle success})
    .catch(err => {res.status(500).json({id:"sql_error",message:err}})
}

正如你所看到的那样,我正在写捕获两次,而且两次我都在写相同的响应500状态并以相同的方式处理捕获。有没有什么好方法可以将这2个捕获量合并为一个?

4 个答案:

答案 0 :(得分:1)

请注意,在您当前编写代码的方式中,您没有返回任何内容,并且以下任何语句都会假设一切正常,因为您已经处理catch并转换响应。

我认为您可以通过以下方式重写您的陈述:



function sanitizeInput( input ) {
  if (input % 2 === 0) {
    throw 'Cannot input even number';
  }
  return input;
}

function dbCreateRowPromise( input ) {
  return Promise.resolve(input);
}

function my_function( input ) {
  return Promise.resolve(input)
    .then( sanitizeInput )
    .then( dbCreateRowPromise );
}

// perfectly normall input
my_function(5)
  .then( out => console.log(out))
  .catch( err => console.log('error occured', err));
  
// errourness input
my_function(4)
  .then( out => console.log(out))
  .catch( err => console.log('error occured', err));




只需使用promises来构建一系列事件,并抛出错误。如果被调用者没有处理它,错误将最终显示在控制台中。

答案 1 :(得分:1)

您遇到的似乎是同步代码,promises和异步回调的混合,它们具有不同的错误处理技术。

一种解决方案就是做你正在做的事情,单独处理不同类型的错误,但这可能会让人感到困惑和复杂。另一种方法是尝试将所有这些代码统一为单一样式,使用简单的抽象来平滑它们。

我个人会尝试将所有调用规范化为异步回调样式调用,然后以这种方式统一错误处理。例如,看起来你在这里使用express中间件,所以我会将所有错误传递出来并在错误处理程序中间件中处理它们。

import { auto, constant } from 'async'
const { assign } from Object

function sanitize (opts, callback) {
  const { input } = opts
  try {
    sanitizeInput(input)
    callback()
  } catch (err) {
    callback(assign(err, { status: 'sanitize_error', statusCode: 500 })
  }
}

function createRow (opts, callback) {
  const { santizie: input } = opts
  dbCreateRowPromise(input)
    .then(result => callback(null, result))
    .catch(err => callback(assign(err, { status: 'create_row_error', statusCode: 500 }))
}

function my_function(req, res, input, next) {
  const block = {
    input: constant(input),
    sanitize: ['input', sanitize],
    createRow: ['sanitize', createRow]
  }

  auto(block, (err, result) => {
    if (err) return next(err)
    res.status(200).json({ status: 'ok' }))
  })
}

function errorHandler(err, req, res) {
  res.status(err.statusCode).json(err)
}

答案 2 :(得分:1)

您应该考虑让sanitizeInput返回一个承诺。然后你可以写:

sanitizeInput(input)
.then(function(data)){
   return dbCreateRowPromise(input);
})
.then(function(data)){
   //success
})
.catch(function(error)){
   //all failures
})

我假设你的函数返回一些东西 - 如果不是data就会返回

答案 3 :(得分:0)

最简单的方法是为您的函数使用async / await语法:

async function my_function(req, res, input) {
  try {
    input = sanitizeInput(input);
    let result = await dbCreateRowPromise(input);
    // handle result
  } catch (err) {
    res.status(500).json({id:"sql_error",message:err});
  }
}

或者,为sanitizeInput做出承诺,以便您可以使用保证链并将错误处理为拒绝。

var promise;
try {
  promise = Promise.resolve(sanitizeInput(input));
} catch (err) {
  promise = Promise.reject(err);
}
promise.then(input => 
  dbCreateRowPromise(input)
).then(result => {
  // Handle success
}).catch(err => {
  res.status(500).json({id:"sql_error",message:err});
});

new Promise(resolve =>
  resolve(sanitizeInput(input))
).then(input =>
  dbCreateRowPromise(input)
).then(…).catch(…);

Promise.resolve(input).then(sanitizeInput).then(dbCreateRowPromise).then(…).catch(…)