一、概念
首先我们要理解Generator和Promise的概念。
Generator:意思是生成器,可以在函数内部通过yeild来控制语句的执行或暂停状态。
*Foo(){ yeild console.log('step1'); yeild console.log('step2'); } run(foo){ var step = foo(); while(!step.done){ step.next(); } } run(Foo); // step1 // step2
通过上面这个例子可以看到,使用*将Foo声明为Generator函数,然后再执行Foo的时候,不会执行到底,而是执行到第一句yeild就停下来。只有调用next()才会执行到下一步yeild。
Promise:是ES6新增的一个对象,相当于一个容器,是用来专门处理异步处理的。
function request = new Promise((resolve,reject) => { $.ajax({ type: "GET", url: "/someajaxurl", contentType: "application/json", dataType: "json", success: function (data) { resolve(data); }, error: function (xhr) { reject(xhr); } }); }).then(data=>{ // success method }).catch(xhr=>{ // error method });
二、Generator和Promise的结合
假设我们有个需求,需要调用两个接口,并且这两个接口不能同时启动异步调用,而是要先调接口1,在调接口2。
那么在没有使用Generator的情况下是这么写的。
// 使用promise异步调用数据 request(url){ return new Promise((resolve,reject) => { $.ajax({ type: "GET", url: "/someajaxurl", contentType: "application/json", dataType: "json", success: function (data) { resolve(data); }, error: function (xhr) { reject(xhr); } }); }); } // 先调用接口1,再点用接口2 gen(){ var nameList = []; request('user/name1').then(data => { nameList.push(data) ; request('user/name2').then(data => { nameList.push(data) }); }); } gen();
以上例子会发现最终会有一个长嵌套的回调函数。
如果我们使用Generator的话,那么代码如下:
// 使用promise异步调用数据 request(url){ return new Promise((resolve,reject) => { $.ajax({ type: "GET", url: "/someajaxurl", contentType: "application/json", dataType: "json", success: function (data) { resolve(data); }, error: function (xhr) { reject(xhr); } }); }); } // 使用generator,将回调函数嵌套的写法改为同步写法 *gen(){ var nameList = []; yeild request('user/name1').then(data => { nameList.push(data) }); yeild request('user/name2').then(data => { nameList.push(data) }); } // 执行generator的next方式 (function(){ var step = gen(); while(!step.done){ step.next(); } });
使用generator的写法,会发现省去一大堆的嵌套,代码变得直观很多。
三、Async
上面的例子,发现代码变得直观了,但是还需要另外写个方法去执行generator。这时候ES6中的新特性Async,还可以对代码做进一步的优化。
// 使用async,效果和generator差不多,只不过将函数内部的yeild改为await.但是async自带执行器,不需要另外再写个方法去执行next. async gen(){ var nameList = []; await request('user/name1').then(data => { nameList.push(data) }); await request('user/name2').then(data => { nameList.push(data) }); }