返回
突破框架,发现JS异步流控制新世界
前端
2023-12-02 19:47:55
异步新世界
最近使用Egg写了一个Node项目,它的异步流控制功能真是让人惊艳,不禁泪流满面。废话不多说,先来看一段代码,体验一下这种奇妙的感觉:
const findPerson = async () => {
// 异步查找人员信息
return await Person.findOne({ name: 'John Doe' });
};
const findOrder = async (person) => {
// 异步查找订单信息
return await Order.findOne({ personId: person._id });
};
const payOrder = async (order) => {
// 异步支付订单
return await Payment.pay(order.id);
};
const purchase = async () => {
// 串行执行异步任务
const person = await findPerson();
const order = await findOrder(person);
const result = await payOrder(order);
// 返回支付结果
return result;
};
以上代码是付款的简易流程,先找人,再找订单,最后支付。其中找人、找订单和支付都是异步逻辑。写出这段代码的时候,回忆把我带到了Callback的时代。Callback是我们最熟悉的异步控制方式,但它存在着明显的缺点:
- 代码混乱、嵌套严重,可读性差
- 调试困难,错误处理复杂
- 难以维护,扩展性差
为了解决这些问题,JS引入了多种异步控制方式,包括:
- 协程(Coroutine)
- 生成器(Generator)
- Promise
- Async/Await
协程与生成器
协程是一种轻量级的线程,它可以暂停自己的执行,并在稍后继续执行。生成器是协程的实现方式之一,它允许我们在函数中使用yield
暂停函数的执行,并在稍后使用next()
方法继续执行。
使用协程和生成器进行异步控制,可以大大提高代码的可读性和可维护性。例如,我们可以使用生成器重写上面的代码:
async function* purchase() {
// 异步查找人员信息
const person = yield findPerson();
// 异步查找订单信息
const order = yield findOrder(person);
// 异步支付订单
const result = yield payOrder(order);
// 返回支付结果
return result;
}
// 使用生成器函数进行异步控制
const purchaseFlow = purchase();
purchaseFlow.next().value.then((result) => {
const order = result.value;
purchaseFlow.next(order).value.then((result) => {
const paymentResult = result.value;
purchaseFlow.next(paymentResult);
});
});
Promise
Promise是一种表示异步操作的最终完成或失败的返回值。Promise对象有两个状态:resolved
和rejected
。resolved
表示异步操作成功完成,rejected
表示异步操作失败。
使用Promise进行异步控制,可以大大提高代码的可读性和可维护性。例如,我们可以使用Promise重写上面的代码:
const purchase = async () => {
// 异步查找人员信息
const person = await findPerson();
// 异步查找订单信息
const order = await findOrder(person);
// 异步支付订单
const result = await payOrder(order);
// 返回支付结果
return result;
};
Async/Await
Async/Await是ES8中引入的异步控制语法糖,它允许我们使用async
和await
关键字来编写异步代码,就像编写同步代码一样。
使用Async/Await进行异步控制,可以大大提高代码的可读性和可维护性。例如,我们可以使用Async/Await重写上面的代码:
const purchase = async () => {
// 异步查找人员信息
const person = await findPerson();
// 异步查找订单信息
const order = await findOrder(person);
// 异步支付订单
const result = await payOrder(order);
// 返回支付结果
return result;
};
结语
JS提供了多种异步控制方式,包括协程、生成器、Promise和Async/Await。这些异步控制方式各有优缺点,我们可以根据具体情况选择合适的异步控制方式。