简体   繁体   English

在不重复代码的情况下处理/捕获错误?

[英]Handle/catch errors without repeating code?

Consider the following (pseudo)function to update a database: 考虑以下(伪)函数来更新数据库:

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

As you can see I'm writting catch twice and both times I'm writing the same response 500 status and handling the catch in the same way. 如您所见,我编写了两次catch,两次都写相同的响应500状态并以相同的方式处理catch。 Is there any good way to combine this 2 catches in a single one? 有什么好的方法可以将这两个渔获物组合成一个渔获物吗?

Note that in your current way of writing the code, you are not returning anything, and any following statements will assume that everything went ok, as you are handling the catch already, and transform the response. 请注意,在当前的代码编写方式中,您不会返回任何内容,并且以下任何语句都将假定一切正常,因为您已经在处理catch并转换了响应。

I think you could just rewrite your statement in the following way: 我认为您可以通过以下方式重写语句:

 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)); 

Just use the promises to build a chain of events, and let the error be thrown. 只需使用Promise构建事件链,然后抛出错误即可。 In case it is not handled by the callee, the error will be shown in the console eventually. 如果被呼叫者未处理,则错误最终将显示在控制台中。

It seems like what you're encountering is a mixture of synchronous code, promises and async callbacks which have different error handling techniques. 似乎您遇到的是同步代码,promise和异步回调的混合体,它们具有不同的错误处理技术。

One solution is to just do what you're doing, handle the different styles of errors individually, but this could get confusing and complicated. 一种解决方案是仅执行您正在做的事情,分别处理不同样式的错误,但这可能会造成混乱和复杂。 The other is to attempt to unify all such code into a single style, using simple abstractions to smooth them over. 另一种方法是尝试使用简单的抽象将所有此类代码统一为一个样式。

I would personally attempt to normalize all of my calls as async callback style calls and then unify the error handling this way. 我个人将尝试将所有调用规范化为异步回调样式调用,然后以这种方式统一错误处理。 For example it looks like you're using express middleware here, so I would pass all errors out and handle them in an error handler middleware. 例如,您似乎在这里使用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)
}

You should consider making sanitizeInput return a promise. 您应该考虑使sanitizeInput返回承诺。 Then you can write: 然后您可以编写:

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

I am assuming your functions return something - if not data would just be null 我假设您的函数返回一些东西-如果不是, data将只是null

The easiest way is to use async / await syntax for your function: 最简单的方法是对函数使用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});
  }
}

Alternatively, make a promise for sanitizeInput so that you can use promise chaining and handle errors from it as a rejection. 或者,对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});
});

or 要么

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

or 要么

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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