有没有办法将等待/异步 try/catch 块包装到每个函数?
Posted
技术标签:
【中文标题】有没有办法将等待/异步 try/catch 块包装到每个函数?【英文标题】:Is there a way to wrap an await/async try/catch block to every function? 【发布时间】:2017-05-11 23:39:56 【问题描述】:所以我正在使用 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);
);
有关非异步示例,请参阅 Is there a way to add try-catch to every function in javascript?。
【问题讨论】:
只使用 express-promise 如果不使包装函数异步,就无法包装 await。在这种情况下,为什么不直接使用.then()
和.catch()
。什么是await
买你。错误处理需要在那里。您不能只希望它用于其他功能。
我正在寻找在可能需要分叉时删除嵌套的then
语句的方法。上面的代码只是一个示范性的例子。
@Neverlax - 你需要更具体地说明你在问什么。在上面的内容中不需要嵌套的 .then()
处理程序 - 如果需要对多个异步操作进行排序,则可以链接。您无法隐藏错误处理并尝试是傻瓜的差事。 await
的一大缺点是人们倾向于只更改错误处理,而 .then()
和 .catch()
对它的需求更为明显。你仍然可以用await
来做,但它需要`try/catch。请使用与您要询问的内容一样复杂的真实代码。
@jfriend00 感谢您的评论。当我问Is there a way that I can still catch errors but get rid of the try/catch block scaffold
时,我感觉很清楚
【参考方案1】:
所以,异步函数实际上是承诺,我想出了这个解决方案:
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);
)();
【讨论】:
【参考方案2】:如果有人更喜欢 async/await 和 Express 特定的方法,那么使用 sn-p 可能会很有用
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));
【讨论】:
【参考方案3】:类似的回答here希望能帮到你
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);
);
【讨论】:
【参考方案4】:是的,您也可以轻松地为异步函数编写这样的包装器 - 只需使用 async
/await
:
function wrapper(f)
return async function()
// ^^^^^
try
return await f.apply(this, arguments);
// ^^^^^
catch(e)
customErrorHandler(e)
或者你直接使用promises,就像这个例子中更适合表达(尤其是参数的数量):
function promiseWrapper(fn)
return (req, res, next) =>
fn(req, res).catch(next);
;
【讨论】:
这确实有效。但是,需要将 async 应用于返回的函数而不是实际的包装函数。您能否进行该编辑以便我可以将其标记为答案?谢谢! 是的,它是一个箭头函数,但普通函数也可以。重要的是它们是正式声明的参数,即promiseWrapper(…).length == 3
,用于区分处理程序。
你能帮我解释一下吗,因为我对 Express 和 Javascript 还很陌生,很难理解它是如何工作的。我没有得到这样一个事实,即我们正在返回一个正在执行原始函数 (fn) 的函数,但它在实践中是如何执行的
@ankshukla "事实上我们正在返回一个正在执行原始函数的函数" - 看起来你确实明白了 :-) 不知道还有什么说。您可能想了解一般的闭包?或者您不确定wrapper
是如何应用的?以上是关于有没有办法将等待/异步 try/catch 块包装到每个函数?的主要内容,如果未能解决你的问题,请参考以下文章
在 ExpressJS 响应中返回异步等待 try/catch 抛出错误 [重复]