【ES6】Generator+Promise异步编程

一、概念

首先我们要理解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) });
}

  

 

posted @ 2017-08-16 11:31  のんきネコ  阅读(395)  评论(0编辑  收藏  举报