需求:使用ajar依次发送3次网络请求, 必须前一次发送成功后才能进行下一次的网络请求。
目的:实现把异步代码的风格写成了同步代码的风格。这个就是Promise + Generator 结合的精髓
1.jQuery中ajar的实现
使用ajar依次发送3次网络请求, 第一次请求user.json, 请求成功后发起第二次网络请求获取banners.json , 第二次获取banners.json成功后接着继续发送第三次网络请求获取goods.json。
在进入主题之前先回顾一下jQuery中ajar的实现过程
<script src="jquery-1.11.3.min.js"></script>
<script> /*1.第一次*/ $.ajax({ url:'user.json', dataType:'json', success:function (res1) { /*2.第二次*/ console.log(res1); $.ajax({ url:'banners.json', dataType:'json', success:function (res2) { /*3.第三次*/ console.log(res2); $.ajax({ url:'goods.json', dataType:'json', success:function (res3) { console.log(res3); }, error:function (error) { console.log(error); } }) }, error:function (error) { console.log(error); } }) }, error:function (error) { console.log(error); } }) </script>
2.Promise + ajar 实现
在回顾一下Promise + ajar的实现过程
<script src="jquery-1.11.3.min.js"></script>
<script> /*1.第一次*/ var promise1=new Promise(function (resolve,reject) { $.ajax({ url:'user.json', dataType:'json', success:function (res1) { resolve(res1) }, error:function (error) { reject(error) } }) }) /*2.第二次*/ var promise2=new Promise(function (resolve,reject) { $.ajax({ url:'banners.json', dataType:'json', success:function (res2) { resolve(res2) }, error:function (error) { reject(error) } }) }) /*3.第二次*/ var promise3=new Promise(function (resolve,reject) { $.ajax({ url:'goods.json', dataType:'json', success:function (res3) { resolve(res3) }, error:function (error) { reject(error) } }) }) /*1.第一次*/ promise1.then( function (res1) { console.log(res1); /*2.第二次*/ promise2.then( function (res2) { console.log(res2); /*3.第三次*/ promise3.then( function (res3) { console.log(res3); }, function (error) { }) }, function (error) { }) }, function (error) { }) </script>
对上面的代码的简写:
<script src="jquery-1.11.3.min.js"></script>
<script> /*1.第一次*/ Promise.all([ $.ajax({url:'user.json',dataType:'json',}) ]).then( function (res1) { console.log(res1); /*2.第二次*/ Promise.all([ $.ajax({url:'banners.json',dataType:'json',}) ]).then( function (res2) { console.log(res2); /*3.第三次*/ Promise.all([ $.ajax({url:'goods.json',dataType:'json',}) ]).then( function (res3) { console.log(res3); }, function (error) { }) }, function (error) { }) }, function (error) { }) </script>
上面的代码虽然可以实现,但是没有实现把异步代码的风格写成了同步代码的风格。异步还是通过回调,回调,回调的方式。下面正式进入主题。
3. Promise + Generator + ajar 实现
正式进入主题:用Promise + Generator + ajar 实现上面的需求
<script src="jquery-1.11.3.min.js"></script>
<script>
/** * 1.定义一个generator函数 *myFetchs * */
function *myFetchs() {
/** * 1.1第一次网络请求 * $.ajax({url:'user.json',dataType:'json'}) : 作为第一次调用next的返回值,是promise对象 * promise1 : 第二次调用next函数中的参数 */
var promise1=yield $.ajax({url:'user.json',dataType:'json'});
/** * 1.2第二次网络请求 * $.ajax({url:'user.json',dataType:'json'}) : 作为第二次调用next的返回值,是promise对象 * promise2 : 第三次调用next函数中的参数 */
var promise2=yield $.ajax({url:'banners.json',dataType:'json'});
/** * 1.3 第三次网络请求 * return promise3 : 作为第三次调用next的返回值,是promise对象 */
var promise3=$.ajax({url:'goods.json',dataType:'json'});
return promise3;
}
/** * 2.获取generatorObj对象(迭代器对象) */
var generatorObj=myFetchs();
/**3.开始执行*myFetch函数*/
/*3.1发起第一次网络请求*/
var result1=generatorObj.next(); //第一次调用next函数
var promise1=result1.value;
promise1.then(
//如果第一次请求成功
function (res1) {
console.log(res1);
/*3.2发起第二次网络请求*/
var result2=generatorObj.next('promise1='+res1); //第二次调用next函数
var promise2=result2.value;
promise2.then(function (res2) {
console.log(res2);
/*3.3发起第三次网络请求*/
var result3=generatorObj.next('promise2='+res1); //第三次调用next函数
var promise3=result3.value;
promise3.then(function (res3) {
console.log(res3);
},function (error) {
})
},function (error) {
})
},
function (error) {
})
</script>
上面的代码已经实现上面所说的需求,但是代码还是比较复杂。为了简化代码,接下来抽取并封装一下代码
把上面的代码封装一下:
封装后的代码如下,这下发起3次网路请求的代码看起来精简了很多,
并且这里已经实现把异步代码的风格写成同步代码的风格。
这个就是Promise + Generator 结合的精髓
/** * 依次发起3次网络请求精简版 * */
runGeneratorFunction(function *() {
//发送第一次网络请求
var promise1=yield $.ajax({url:'user.json',dataType:'json'});
//发送第二次网络请求
var promise2=yield $.ajax({url:'banners.json',dataType:'json'});
//发送第三次网络请求
var promise3=$.ajax({url:'goods.json',dataType:'json'});
return promise3;
})
其中runGeneratorFunction函数的简单实现
/** * 负债运行Generator函数,参数是一个Generator函数 */
function runGeneratorFunction(genFunction) {
/** * 2.获取generatorObj对象(迭代器对象) */
var generatorObj=genFunction();
/**3.开始执行*myFetch函数*/
/*3.1发起第一次网络请求*/
var result1=generatorObj.next(); //第一次调用next函数
var promise1=result1.value;
promise1.then(
//如果第一次请求成功
function (res1) {
console.log(res1);
/*3.2发起第二次网络请求*/
var result2=generatorObj.next('promise1='+res1); //第二次调用next函数
var promise2=result2.value;
promise2.then(function (res2) {
console.log(res2);
/*3.3发起第三次网络请求*/
var result3=generatorObj.next('promise2='+res2); //第三次调用next函数
var promise3=result3.value;
promise3.then(function (res3) {
console.log(res3);
},function (error) {
})
},function (error) {
})
},
function (error) {
})
}