Javascript 使用Async/Await更正Try…Catch语法
我喜欢Typescript中新的Javascript 使用Async/Await更正Try…Catch语法,javascript,promise,async-await,try-catch,ecmascript-2017,Javascript,Promise,Async Await,Try Catch,Ecmascript 2017,我喜欢Typescript中新的Async/Await功能的平坦性,等等。但是,我不确定我是否喜欢这样一个事实:我必须在try…catch块的外部声明变量I'mAwaiting,以便以后使用它。像这样: let createdUser try { createdUser = await this.User.create(userInfo) } catch (error) { console.error(error) } console.log(createdUser) // b
Async/Await
功能的平坦性,等等。但是,我不确定我是否喜欢这样一个事实:我必须在try…catch
块的外部声明变量I'mAwait
ing,以便以后使用它。像这样:
let createdUser
try {
createdUser = await this.User.create(userInfo)
} catch (error) {
console.error(error)
}
console.log(createdUser)
// business
// logic
// goes
// here
如果我错了,请纠正我,但最好不要在try
正文中放置多行业务逻辑,因此我只能选择在块外声明createdUser
,在块中分配它,然后在之后使用它
在这种情况下,最佳做法是什么
在try主体中不放置多行业务逻辑似乎是最佳实践
事实上我想说是的。您通常希望捕获使用该值时出现的所有异常:
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
}
如果您只想捕获和处理承诺中的错误,您有三种选择:
- 在外部声明变量,并根据是否存在异常进行分支。可以采取多种形式,比如
- 为
块中的变量指定默认值catch
early或re-return
从
块抛出异常catch
- 设置标记
块是否捕获异常,并在catch
条件下测试异常if
- 测试要分配的变量的值
- 为
- 测试捕获的异常的类型,并基于该类型处理或重新引用它
不幸的是,标准JavaScript(仍然)没有对的语法支持 如果您的方法没有返回因特定错误而被拒绝的承诺,您可以通过在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; } }
处理程序中重新抛出更合适的内容来实现这一点:.catch()
另请参阅此文件的预try { const createdUser = await this.User.create(userInfo).catch(err => { throw new CreationError(err.message, {code: "USER_CREATE"}); }); … } …
/异步
版本等待
- 使用而不是
/尝试
。这确实是最不丑陋的方式,我个人的建议也是因为它的简单性和正确性,不依赖标记的错误或结果值的外观来区分承诺的履行和拒绝:捕获
当然,它也有引入回调函数的缺点,这意味着您不能轻易地await this.User.create(userInfo).then(createdUser => { // user was successfully created console.log(createdUser) // business logic goes here }, error => { console.error(error) // from creation });
/中断
循环,或者从外部函数提前执行继续
s返回
const createdUser = await this.User.create(userInfo).catch( error => {
// handle error
})
@Bergi的答案很好,但我认为这不是最好的方法,因为必须回到旧的then()方法,所以我认为更好的方法是捕获异步函数中的错误
async function someAsyncFunction(){
const createdUser = await this.User.create(userInfo);
console.log(createdUser)
}
someAsyncFunction().catch(console.log);
- 但是,如果我们在同一个函数中有许多
等待
,并且需要捕获每个错误,该怎么办
to()
函数
function to(promise) {
return promise.then(data => {
return [null, data];
})
.catch(err => [err]);
}
然后
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();
当阅读这篇文章时,它的意思是:“等待this.User.create”
最后,您可以创建模块“to.js”或简单地使用该模块
您可以在中获得有关
to
函数的更多信息。我通常使用Promise的catch()
函数在失败时返回带有error
属性的对象
例如,在你的情况下,我会:
const createdUser=wait this.User.create(userInfo)
.catch(错误=>{error});//({error}));
};
现在您可以执行以下操作:
const createdUser=wait this.User.create.withCatcher(userInfo);
if(对象(createdUser).error){
console.error(createdUser.error);
}
2020年3月编辑 您还可以向
Promise
对象添加默认的“捕获错误对象”函数,如下所示:
Promise.prototype.catchToObj=函数catchToObj(){
返回这个.catch(error=>({error}));
};
然后按如下方式使用:
const createdUser=wait this.User.create(userInfo.catchToObj();
if(createdUser&&createdUser.error){
console.error(createdUser.error);
}
“最佳实践”是使用有效的、可理解的、可维护的等。。我们如何才能“正确”回答这个问题?我只需要使用var
,知道变量将被提升。这是“错误”吗?try/catch应该准确地包含您想要捕获异常的内容。如果明确查找来自this.User.create()
的错误,则不会在try/catch中放入任何其他内容。但是,在一个try块中放入一大堆逻辑也是一个非常合理的设计。这完全取决于您希望如何/在何处处理错误,以及您希望如何设计异常处理代码,以及对给定操作有何意义。没有通用的最佳实践。一个通用的最佳实践是确保以适当的方式捕获和处理所有错误。async/await
是ES2017(今年的版本)的一部分,而不是ES6(两年前发布)。您的上一个示例使用.then()
来解决承诺并提供回调,因此,wait
可能没有任何效果。@dcorking它是wait
在等待返回的承诺。然后(…)
调用。.then()
调用返回的lambda是否需要async关键字?我见过有人直接附加catch处理程序来等待。这样做是个好主意还是将其包装在try/catch中?@Sarojconst result=wait something().catch(err=>fallback)
比let结果更简单;尝试{{结果=等待某事();} catch(Err){结果=后退;}:是的,在这种情况下,我认为这是个好主意。<代码>那么不比<代码>更糟,请等待< /C> >因为它更旧了。它只是不同,而且适合其他事情。另一方面,这种“wait to(…)
样式”让人想起了具有所有缺点的nodeback样式。顺便说一句,为了获得更好的性能和简单性,您应该使用
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();