用await-to-js让Promise操作更简洁
创作时间:
作者:
@小白创作中心
用await-to-js让Promise操作更简洁
引用
1
来源
1.
https://codlin.me/blog-program/await-to-js-keeps-your-promises-slick
前阵子意外注意到一个有趣的库,名为await-to-js。这个库的主要用途是提供一种新的Promise与await的写法,可以在特定情境下让代码更简洁。类似的实现Radash也有,不过await-to-js的用法比较单纯。
具体差异在哪里?
假设原本的Promise是这样:
let isLoading = true
task()
.then(() => {
isLoading = false
})
.catch((e) => {
console.error('error')
isLoading = false
})
用await会这样写:
let isLoading = true
try {
await task()
} catch (e) {
console.error('error')
}
isLoading = false
使用await-to-js改写后变成:
import to from 'await-to-js'
let isLoading = true
const [error] = await to(task())
isLoading = false
if (error) {
console.error('error')
return
}
除了看起来比较简洁,不用try catch外,配合early return很有效。在前端可能还好,在后端各种Promise操作的场合的很方便,从此以后写法再也回不去了。
以下是官方的范例:
import to from 'await-to-js'
async function asyncTaskWithCb(cb) {
let err, user, savedTask, notification;
[err, user] = await to(UserModel.findById(1))
if (!user)
return cb('No user found');
[err, savedTask] = await to(TaskModel({ userId: user.id, name: 'Demo Task' }))
if (err)
return cb('Error occurred while saving task')
if (user.notificationsEnabled) {
[err] = await to(NotificationService.sendNotification(user.id, 'Task Created'))
if (err)
return cb('Error while sending notification')
}
if (savedTask.assignedUser.id !== user.id) {
[err, notification] = await to(NotificationService.sendNotification(savedTask.assignedUser.id, 'Task was created for you'))
if (err)
return cb('Error while sending notification')
}
cb(null, savedTask)
}
async function asyncFunctionWithThrow() {
const [err, user] = await to(UserModel.findById(1))
if (!user)
throw new Error('User not found')
}
我自己的话后端比较常用,例如NestJS的Controller中:
@Controller()
export class ArticleController {
// ..
@UseGuards(AuthGuard('jwt'))
async getInfo(
@User() jwtPayload: JwtPayload,
@Body() body: CreateArticleDto,
) {
const [userError, result] = await to(
this.userService.check(jwtPayload)
)
if (userError) {
throw new HttpException(
`用户身份异常`,
HttpStatus.FORBIDDEN,
)
}
const [checkError, result] = await to(
this.articleService.checkQuota(jwtPayload)
)
if (checkError) {
throw new HttpException(
`建立文章失败,请稍后再试`,
HttpStatus.INTERNAL_SERVER_ERROR,
)
}
if (result.reason === 'quota-has-been-used-up') {
throw new HttpException(
`文章额度已满,请联系客服`,
HttpStatus.BAD_REQUEST,
)
}
const [createError, article] = await to(
this.articleService.create(body)
)
if (createError) {
throw new HttpException(
`建立文章失败,请稍后再试`,
HttpStatus.INTERNAL_SERVER_ERROR,
)
}
return article
}
}
可以提前处理error,更方便使用early return。
await-to-js的实现很简单,他的原始码只有22行:
/**
* @param { Promise } promise
* @param {object=} errorExt - Additional Information you can pass to the err object
* @return { Promise }
*/
export function to<T, U = Error>(
promise: Promise<T>,
errorExt?: object
): Promise<[U, undefined] | [null, T]> {
return promise
.then<[null, T]>((data: T) => [null, data])
.catch<[U, undefined]>((err: U) => {
if (errorExt) {
const parsedError = Object.assign({}, err, errorExt)
return [parsedError, undefined]
}
return [err, undefined]
})
}
export default to
如果不想npm install的话,也可以直接贴到自己的专案使用。
Promise都改用await to吗?
当然不是这样啦,await to只是多一个选择。实际上还是有些地方更适合使用then或try catch。
例如:
- 有时候根本就不会有错误,就维持await。
- 有错误也无所谓,不需要特别处理,用catch记录一下就行。
- 单一错误不重要,统一处理即可,就直接try catch。
请依照实际状况挑选适合的写法。
总结
- await-to-js可以在特定情境下简化Promise写法
- 配合early return很有效
- 请不要只用await-to-js,需要用then或try catch还是用原本的写法
热门推荐
糖尿病患者,如何管理双足?
河南自驾旅游攻略,探寻最全最好线路,你准备好了吗?
周璇,12张杂志封面照,落入人间的天使,曾经歌影双栖的女明星
刑事辩护中的无罪辩护策略
全球嘻哈潮流与中国本土化
中国神话体系:一个渐进发展的文化瑰宝
过年“亲子数学游戏”教学实操《用“数手指”游戏来“算命”》(适合1-6年级)
龙砂医学流派:《三因方》审平汤的现代应用
刀郎新歌《翩翩》歌词赏析:一首蕴含人生哲理的唯美之作
送别诗词大家叶嘉莹 人生不可以不读诗
乔治亚理工学院校友登上福布斯富豪榜:艾伦·阿尔德里奇和比尔·福特
乔治亚理工学院PK清华北大:谁是全球教育王者?
8个网红“悬崖民宿” ,超级出圈
民宿项目功能规划指南:从定位到运营管理的全方位解析
秋冬打卡圣地:西九华山中原竹寨&白鹭湖民宿
冬游西九华山:禅意茶香中的冰雪世界
春游西九华山:茶园竹海间,尽享禅意与民俗
二战时期美国如何支援中国抗日?
德苏美三国如何助力中国抗战?
国开债投资指南:安全还是陷阱?
“24国开15”首笔成交收益率上行!投资机会来了?
冬日打卡:洛阳龙门石窟最美摄影指南
迈克尔·杰克逊:流行音乐的无冕之王,跨时代文化现象的缔造者
八朝古都开封,你知道是哪八朝吗?
流行音乐:从西方到东方的演变与创新
香港的“罗马地下宫殿”:前深水埗配水库的百年传奇
深水埗:香港的文化瑰宝与人文魅力
深水埗霓虹灯展:传统与现代的光影对话
“音乐慢综”首创之作,《时光音乐会》有哪些创新?
从“十不葬”到现代家居风水:健康居住环境的智慧传承