异步编程的解决方案

首先先明白一点,异步编程的目标就是怎样让它更像同步编程。

异步编程的解决方案有哪些?

1、回调

2、事件发布订阅

3、Promise

4、Generator

5、async/await

回调

由于node涉及大量的异步操作,所以回调非常常见。

fs.readFile('某个文件', function (err, data) {
  if (err) throw err;
  console.log(data);
});

回调的问题,第一个就是异常处理,无法再使用try-catch捕获错误,Node在处理异常有一个约定,将异常作为回调的第一个实参传回,如果为空表示没有出错。

异步多级依赖的情况下嵌套非常深,代码难以阅读的维护,也就是我们常说的回调地狱的问题。

发布订阅

订阅事件实现了一个事件与多个回调函数的关联(一对多),是多个异步之间的协作方案。

回调函数可以任意的添加和删除,也可以隔离业务逻辑,保持业务逻辑单元的职责单一。

const EventEmitter = require('events');


class MyEmitter extends EventEmitter {}


const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
  console.log('an event occurred!');
});
myEmitter.on('event', () => {
  console.log('an event occurred!');
});
myEmitter.emit('event');

使用事件的方式时,执行流程需要被预先设定,这是有发布订阅模式机制所决定的,Promise 可以先执行异步调用,延迟传递处理的方法。

Promise

Promise是高级接口,发布订阅模式是低级接口。低级接口可以构成更多更复杂的场景,高级接口一旦定义,不太容易变化,不再有低级接口的灵活性,但对于解决典型问题非常有效。

fetch(url, options).then(function(response) { 
  console.log(res);
}, function(error) {
  console.log(e.code) // ENOTFOUND
})

生成器Generators

co 是 TJ 大神基于 ES6 generator 的异步解决方案。要理解 co 你得先理解 ES6 generator,这里就不赘述了。co 最大的好处就是能让你把异步的代码流程用同步的方式写出来,并且可以用 try/catch:

co(function *(){
  try {
    var res = yield fetch(url, options);
    console.log(res);
  } catch(e) {
    console.log(e.code) // ENOTFOUND
 }
})()

但用 co 的一个代价是 yield 后面的函数必须返回一个 Thunk 或者一个 Promise,对于现有的 API 也得进行一定程度的二次封装。

async/await

async function showStuff () {
  var data = await loadData() // loadData 返回一个 Promise
  console.log(data) // data 已经加载完毕
}


async function todo () {
  await showStuff() // async 函数默认返回一个 Promise, 所以可以 await 另一个 async 函数
  // 这里 showStuff 已经执行完毕
}

一比较就会发现,async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await,仅此而已。

Generator 函数的执行必须靠执行器,所以才有了co模块,而async函数自带执行器。也就是说,async函数的执行,与普通函数一模一样,只要一行。

可以看到,和用 co 写出来的代码很像,但语意上更清晰。因为本质上 ES7 async/await 就是基于 Promise + generator 的一套语法糖。

总结:解决问题的方式有很多种,我们还是需要具体问题具体分析,根据不同的场景使用最佳的编码方式才是最好的选择。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值