需求:使用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) {
})
}