Javascript 正确的 Try...Catch 语法使用 Async/Await
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/44663864/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Correct Try...Catch Syntax Using Async/Await
提问by freedomflyer
I like the flatness of the new Async/Awaitfeature available in Typescript, etc. However, I'm not sure I like the fact that I have to declare the variable I'm awaiting on the outside of a try...catchblock in order to use it later. Like so:
我喜欢Async/AwaitTypescript 等中可用的新功能的平坦性。但是,我不确定我是否喜欢这样一个事实,即我必须await在try...catch块的外部声明我ing的变量以便以后使用它。像这样:
let createdUser
try {
createdUser = await this.User.create(userInfo)
} catch (error) {
console.error(error)
}
console.log(createdUser)
// business
// logic
// goes
// here
Please correct me if I'm wrong, but it seems to be best practice notto place multiple lines of business logic in the trybody, so I'm left only with the alternative of declaring createdUseroutside the block, assigning it in the block, and then using it after.
如果我错了,请纠正我,但最好不要在try正文中放置多行业务逻辑,所以我只能选择createdUser在块外声明,在块中分配它,以及然后使用它。
What is best practice in this instance?
在这种情况下,最佳实践是什么?
采纳答案by Bergi
It seems to be best practice not to place multiple lines of business logic in the try body
最好不要在 try 主体中放置多行业务逻辑
Actually I'd say it is. You usually want to catchallexceptions from working with the value:
其实我想说的是。您通常希望使用该值排除catch所有异常:
try {
const createdUser = await this.User.create(userInfo);
console.log(createdUser)
// business logic goes here
} catch (error) {
console.error(error) // from creation or business logic
}
If you want to catch and handle errors only from the promise, you have three choices:
如果你只想从 promise 中捕获和处理错误,你有三个选择:
Declare the variable outside, and branch depending on whether there was an exception or not. That can take various forms, like
- assign a default value to the variable in the
catchblock returnearly or re-throwan exception from thecatchblock- set a flag whether the
catchblock caught an exception, and test for it in anifcondition - test for the value of the variable to have been assigned
let createdUser; // or use `var` inside the block try { createdUser = await this.User.create(userInfo); } catch (error) { console.error(error) // from creation } if (createdUser) { // user was successfully created console.log(createdUser) // business logic goes here }- assign a default value to the variable in the
Test the caught exception for its type, and handle or rethrow it based on that.
try { const createdUser = await this.User.create(userInfo); // user was successfully created console.log(createdUser) // business logic goes here } catch (error) { if (error instanceof CreationError) { console.error(error) // from creation } else { throw error; } }Unfortunately, standard JavaScript (still) doesn't have syntax support for conditional exceptions.
Use
thenwith two callbacksinstead oftry/catch. This really is the least ugly way and my personal recommendation also for its simplicity and correctness, not relying on tagged errors or looks of the result value to distinguish between fulfillment and rejection of the promise:await this.User.create(userInfo).then(createdUser => { // user was successfully created console.log(createdUser) // business logic goes here }, error => { console.error(error) // from creation });Of course it comes with the drawback of introducing callback functions, meaning you cannot as easily
break/continueloops or do earlyreturns from the outer function.
在外部声明变量,并根据是否有异常进行分支。这可以采取各种形式,例如
- 为
catch块中的变量分配一个默认值 return早期或重新throw来自catch块的异常- 设置
catch块是否捕获异常的标志,并在if条件下测试它 - 测试变量的值是否已分配
let createdUser; // or use `var` inside the block try { createdUser = await this.User.create(userInfo); } catch (error) { console.error(error) // from creation } if (createdUser) { // user was successfully created console.log(createdUser) // business logic goes here }- 为
测试捕获的异常的类型,并根据它处理或重新抛出它。
try { const createdUser = await this.User.create(userInfo); // user was successfully created console.log(createdUser) // business logic goes here } catch (error) { if (error instanceof CreationError) { console.error(error) // from creation } else { throw error; } }不幸的是,标准 JavaScript(仍然)没有对条件异常的语法支持。
then与两个回调一起使用,而不是try/catch。这确实是最不丑陋的方式,我个人的建议也是因为它的简单性和正确性,不依赖标记的错误或结果值的外观来区分履行和拒绝承诺:await this.User.create(userInfo).then(createdUser => { // user was successfully created console.log(createdUser) // business logic goes here }, error => { console.error(error) // from creation });当然,它带来了引入回调函数的缺点,这意味着您不能轻松
break/continue循环或return从外部函数执行 early s。
回答by nevf
Another simpler approach is to append .catch to the promise function. ex:
另一种更简单的方法是将 .catch 附加到 promise 函数。前任:
const createdUser = await this.User.create(userInfo).catch( error => {
// handle error
})
回答by Arik
I usually use the Promise's catch()function to return an object with an errorproperty on failure.
我通常使用 Promise 的catch()函数error在失败时返回一个具有属性的对象。
For example, in your case i'd do:
例如,在您的情况下,我会这样做:
const createdUser = await this.User.create(userInfo)
.catch(error => { error }); // <--- the added catch
if (Object(createdUser).error) {
console.error(error)
}
If you don't like to keep adding the catch()calls, you can add a helper function to the Function's prototype:
如果你不想继续添加catch()调用,你可以在函数的原型中添加一个辅助函数:
Function.prototype.withCatcher = function withCatcher() {
const result = this.apply(this, arguments);
if (!Object(result).catch) {
throw `${this.name}() must return a Promise when using withCatcher()`;
}
return result.catch(error => ({ error }));
};
And now you'll be able to do:
现在您将能够执行以下操作:
const createdUser = await this.User.create.withCatcher(userInfo);
if (Object(createdUser).error) {
console.error(createdUser.error);
}
编辑 03/2020
You can also add a default "catch to an error object" function to the Promiseobject like so:
您还可以向对象添加默认的“捕获到错误对象”函数,Promise如下所示:
Promise.prototype.catchToObj = function catchToObj() {
return this.catch(error => ({ error }));
};
And then use it as follows:
然后按如下方式使用它:
const createdUser = await this.User.create(userInfo).catchToObj();
if (createdUser && createdUser.error) {
console.error(createdUser.error);
}
回答by Ivan
@Bergi Answer is good, but I think it's not the best way because you have to go back to the old then() method, so i think a better way is to catch the error in the async function
@Bergi 答案很好,但我认为这不是最好的方法,因为您必须回到旧的 then() 方法,所以我认为更好的方法是捕获异步函数中的错误
async function someAsyncFunction(){
const createdUser = await this.User.create(userInfo);
console.log(createdUser)
}
someAsyncFunction().catch(console.log);
- But what if we have many
awaitin the same function and need to catch every error?
- 但是如果我们
await在同一个函数中有很多并且需要捕获每个错误怎么办?
You may declare the to()function
你可以声明to()函数
function to(promise) {
return promise.then(data => {
return [null, data];
})
.catch(err => [err]);
}
And then
进而
async function someAsyncFunction(){
let err, createdUser, anotherUser;
[err, createdUser] = await to(this.User.create(userInfo));
if (err) console.log(`Error is ${err}`);
else console.log(`createdUser is ${createdUser}`);
[err, anotherUser] = await to(this.User.create(anotherUserInfo));
if (err) console.log(`Error is ${err}`);
else console.log(`anotherUser is ${anotherUser}`);
}
someAsyncFunction();
When reading this its: "Wait to this.User.create".
阅读此内容时:“等待 this.User.create”。
Finally you can create the module "to.js" or simply use the await-to-jsmodule.
最后,您可以创建模块“to.js”或简单地使用await-to-js模块。
You can get more information about tofunction in this post
您可以to在这篇文章中获得有关函数的更多信息

