fre*_*yer 49 javascript try-catch promise async-await ecmascript-2017
我喜欢Async/Await
在Typescript等中提供的新功能的平坦性.但是,我不确定我喜欢这样一个事实,即我必须await
在try...catch
块的外部声明变量才能在以后使用它.像这样:
let createdUser
try {
createdUser = await this.User.create(userInfo)
} catch (error) {
console.error(error)
}
console.log(createdUser)
// business
// logic
// goes
// here
Run Code Online (Sandbox Code Playgroud)
如果我错了,请纠正我,但似乎最好不要在机构中放置多行业务逻辑try
,所以我只留下createdUser
在块外声明,在块中分配它的替代方案,以及然后用它.
在这种情况下,最佳做法是什么?
Ber*_*rgi 39
似乎最好不要在try体中放置多行业务逻辑
其实我会说是的.您通常希望使用该值的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
}
Run Code Online (Sandbox Code Playgroud)
如果您只想从承诺中捕获并处理错误,您有三种选择:
在外部声明变量,并根据是否存在异常进行分支.这可以采取各种形式,如
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
}
Run Code Online (Sandbox Code Playgroud)测试捕获的异常的类型,并根据它处理或重新抛出它.
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;
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,标准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
});
Run Code Online (Sandbox Code Playgroud)
当然它带有引入回调函数的缺点,这意味着你不能轻易地break
/ continue
循环或return
从外部函数做早期.
Cal*_*twr 13
据我所知,这是一个长期存在的问题,困扰着(两种意义上的)许多程序员及其代码。Promise.catch
确实与 没有什么不同try/catch
。
ES6 Promise 的 catch 处理程序并与“await/async”和谐地工作,提供了正确的解决方案和更清晰的代码:
const createUser = await this.User
.create(userInfo)
.catch(error => console.error(error))
console.log(createdUser)
// business
// logic
// goes
// here
Run Code Online (Sandbox Code Playgroud)
请注意,虽然这回答了问题,但它消除了错误。在这种情况下,最好抛出异常,因为 (1) 此操作(创建用户)预计不会失败,并且 (2) 无论如何您都无法继续 - 该操作已出错:
const createUser = await this.User
.create(userInfo)
.catch(error => {
// do what you need with the error
console.error(error)
// maybe send to Datadog or Sentry
// don't gobble up the error
throw error
})
console.log(createdUser)
// business
// logic
// goes
// here
Run Code Online (Sandbox Code Playgroud)
catch
好像不值得?上面的清洁优势可能并不明显,但它会增加现实世界中复杂的异步操作。
举例来说,除了创建用户(this.User.create
)之外,我们还可以推送通知(this.pushNotification
)和发送电子邮件(this.sendEmail
)。
this.User.create
this.User.create = async(userInfo) => {
// collect some fb data and do some background check in parallel
const facebookDetails = await retrieveFacebookAsync(userInfo.email)
.catch(error => {
// we can do some special error handling
// and throw back the error
})
const backgroundCheck = await backgroundCheckAsync(userInfo.passportID)
if (backgroundCheck.pass !== true) throw Error('Background check failed')
// now we can insert everything
const createdUser = await Database.insert({ ...userInfo, ...facebookDetails })
return createdUser
}
Run Code Online (Sandbox Code Playgroud)
this.pushNotifcation和this.sendEmail
this.pushNotification = async(userInfo) => {
const pushed = await PushNotificationProvider.send(userInfo)
return pushed
})
this.sendEmail = async(userInfo) => {
const sent = await mail({ to: userInfo.email, message: 'Welcome' })
return sent
})
Run Code Online (Sandbox Code Playgroud)
编写操作:
const createdUser = await this.User
.create(userInfo)
.catch(error => {
// handle error
})
// business logic here
return await Promise.all([
this.pushNotification(userInfo),
this.sendEmail(userInfo)
]).catch(error => {
// handle errors caused
// by pushNotification or sendEmail
})
Run Code Online (Sandbox Code Playgroud)
没有尝试/捕捉。并且很清楚您正在处理哪些错误。
另一种更简单的方法是将.catch追加到promise函数。例如:
const createdUser = await this.User.create(userInfo).catch( error => {
// handle error
})
Run Code Online (Sandbox Code Playgroud)