以前的异步编程主要分为下面4种:
* 回调函数
* 事件监听
* 发布/订阅
* Promise 对象

1. 什么是异步

异步的概念就是将一个任务分成两段,先执行第一段,然后去执行其他任务,等做好了准备再回来继续执行第二段。

2. 回调函数的概念

回调函数就是把任务的第二段写到一个函数里面,等到需要的时候去执行这个任务。

3. Promise

Promise的出现就是为了解决回调函数的多重嵌套(callback hell)。Promise的问题就是代码冗余,一眼望去一堆的then。

4. 协程

协程(coroutine)意思是多个线程互相协作完成异步任务。
运行流畅如下:
1. 协程A开始执行
2. 协程A执行一半,暂停,转到协程B
3. 一段时间后协程B交还执行权
4. 协程A恢复执行

function asnycJob() {
  // ...其他代码
  var f = yield readFile(fileA);
  // ...其他代码
}

asyncJob就是一个协程,重点就是里面的yield命令,作用是执行到此处时将执行权交给其他协程。

5. Generator函数的概念

Generator最大的特点就是可以交出函数的执行权(暂停执行)

function* gen(x){
  var y = yield x + 2;
  return y;
}

一个Generator函数的特征就是函数名前加星号。异步操作时暂停的地方用yield语句注明。

var g = gen(1);
g.next() // { value: 3, done: false }
g.next() // { value: undefined, done: true }

调用Generator函数,会返回一个内部指针(遍历器)g。Generator函数和普通函数的区别是它返回的不是结果而是指针对象g。然后调用g上面的next()方法,移动内部指针。每次调用g.next()方法会返回一个包含value和done这2个属性的对象。

6. Generator函数的数据交换和错误处理

除了暂停和恢复执行外,Generator还有两个特性:
* 数据交换
* 错误处理

上面的例子中,g.next()方法可以接收参数

function* gen(x){
  var y = yield x + 2;
  return y;
}

var g = gen(1);
g.next() // { value: 3, done: false }
g.next(2) // { value: 2, done: true }

这个参数传入的值是作为上个阶段异步任务的返回结果,所以这2替换的是y的值。

下面是抛出错误的例子:

function* gen(x){
  try {
    var y = yield x + 2;
  } catch (e){ 
    console.log('错误信息:' , e);
  }
  return y;
}

var g = gen(1);
g.next();
g.throw('出错了'); // 错误信息:出错了

7. Generator函数的用法


var fetch = require('node-fetch');

function* gen(){
  var url = 'https://api.github.com/users/github';
  var result = yield fetch(url);
  console.log(result.bio);
}

var g = gen();
var result = g.next();

result.value.then(function(data){
  return data.json();
}).then(function(data){
  g.next(data);
});

首先执行Generator函数获取遍历器g。然后调用g.next()得到返回结果,一个Promise对象然后用Promise的then方法去调用下一个next方法。

转载请注明来自:爱前端

发表评论

电子邮件地址不会被公开。 必填项已用*标注