繁体   English   中英

有没有办法将等待/异步 try/catch 块包装到每个函数?

[英]Is there a way to wrap an await/async try/catch block to every function?

所以我正在使用 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 中的每个函数? 对于非异步示例。

是的,您也可以轻松地为异步函数编写这样的包装器 - 只需使用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);
    };
}

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

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

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

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

const catchAsyncErrors = (func) => (req, res, next) =>
  Promise.resolve(func(req, res, next)).catch((err) => {
    console.log("error", err);
    next();
  });

export default catchAsyncErrors;

然后在控制器中:

const currentUserProfile = catchAsyncErrors(async (req, res) => {
  const user = await User.findById(req.user._id);
  res.status(200).json({
    success: true,
    user,
  });
});

我正在使用 Firebase Functions onRequest 方法为 Express 应用程序提供服务。 此页面上的其他答案帮助我找到了在顶层捕获错误并避免在每个处理程序中都有 try/catch 的解决方案。

关键点是

  • 将异步添加到 onRequest 方法
const admin = functions.https.onRequest(async (req, res) => adminApp(req, res));
// adminApp
const app = express();

// middleware here...

addPostHandler(app, '/createUser', createUser);
//  ...other routes

// error middleware here...
  • 将等待添加到处理程序调用
// addPostHandler
export const addPostHandler = (app, route: string, handler) => {
  app.post(route, async (req: express.Request, res: express.Response, next: express.NextFunction) => {
    // try catch here means we don't need to add inside each handler
    try {
      await handler(req, res);
    } catch (error) {
      return next(error);
    }
  });
};

暂无
暂无

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

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