有没有办法将 await/async try/catch 块包装到每个函数中?

IT技术 javascript express async-await ecmascript-2017
2021-02-12 11:06:38

所以我正在使用 express.js 并考虑在节点 7 中使用 async/await。有没有办法我仍然可以捕获错误但摆脱 try/catch 块?也许是函数包装器?我不确定这将如何实际执行函数的代码并调用next(err).

exports.index = async function(req, res, next) {
  try {
    let user = await User.findOne().exec();

    res.status(200).json(user);
  } catch(err) {
    next(err);
  }
}

这种东西……?

function example() {
   // Implements try/catch block and then handles error.
}

exports.index = async example(req, res, next) {
  let user = await User.findOne().exec();
  res.status(200).json(user);
}

编辑:

更类似的东西:

var wrapper = function(f) {
    return function() {
        try {
            f.apply(this, arguments);
        } catch(e) {
            customErrorHandler(e)
        }
    }
}

这会以某种方式处理 try/catch 块,但不起作用:

exports.index = wrapper(async example(req, res, next) {
  let user = await User.findOne().exec();
  res.status(200).json(user);
});

请参阅是否可以将 try-catch 添加到 Javascript 中的每个函数?对于非异步示例。

4个回答

是的,您也可以轻松地为异步函数编写这样的包装器 - 只需使用async/ await

function wrapper(f) {
    return async function() {
//         ^^^^^
        try {
            return await f.apply(this, arguments);
//                 ^^^^^
        } catch(e) {
            customErrorHandler(e)
        }
    }
}

或者你直接使用promise,就像在这个例子中更适合表达(尤其是参数数量):

function promiseWrapper(fn) {
    return (req, res, next) => {
         fn(req, res).catch(next);
    };
}
这确实有效。但是,异步需要应用于返回的函数而不是实际的包装函数。您可以进行编辑以便我可以将其标记为答案吗?谢谢!
2021-03-15 11:06:38
是的,这是一个箭头函数,但普通函数也可以。重要的是它们是正式声明的参数,即promiseWrapper(…).length == 3表达用于区分处理程序的参数。
2021-03-21 11:06:38

这里有一个类似的答案希望可以帮助你

const sthError = () => Promise.reject('sth error');

const test = opts => {
  return (async () => {

    // do sth
    await sthError();
    return 'ok';

  })().catch(err => {
    console.error(err); // error will be catched there 
  });
};

test().then(ret => {
  console.log(ret);
});

如果有人更喜欢 async/await 和 Express 特定的方法,下面的代码片段可能会有用

export function asyncWrap(fn) {
  return async function wrappedFn(req, res, next) {
    try {
      await fn(req, res);
    } catch (err) {
      next(err);
    }
  };
}

它可以通过以下方式在路由器中使用

customRouter.get('/', asyncWrap(customController.getCustomListHandler));

所以,异步函数实际上是Promise,我想出了这个解决方案:

const asyncWrapper = async promise => {
    try {
        return [null, await promise];
    } catch (err) {
        return [err];
    }
};

const yourAsyncMethod = params => new Promise((resolve, reject) => {
    resolve(params);
});

(async () => {
  // Wrap the executed async method but use the await outside
  const [error, result] = await asyncWrapper(yourAsyncMethod(1));
  
  if (error) {
    // Handle error
  }
  console.log(result);
})();