在Ajax中,需要多个Ajax请求时,新的Ajax请求必须从上一个Ajax请求中获取,这时我们需要不停的嵌套函数,如下:
var url="...";
var result;
var XHR=new XMLHttpRequest();
XHR.open("GET",url,true);
XHR.send();
XHR.onreadystatechange=function(){
if(XHR.readyState == 4 && XHR.status==200){
result=XHR.response;
console.log(result);
//多个请求,伪代码
var url2="...";
var XHR2=new XMLHttpRequest();
XHR2.open("GET",url,true);
XHR2.send();
XHR2.onreadystatechange=function(){
...
}
}
}
回调函数解决
//简单的封装
function want(){
console.log("要执行的代码");
}
function fn(want){
console.log("要执行的代码");
//其他代码执行完毕,最后执行回调函数
want && want();
}
fn(want);
队列机制解决
function want(){
console.log("要执行的代码");
}
function fn(want){
want && setTimeout(want,0);
console.log("要执行的代码");
}
fn(want);
与setTimeout类似,Promise也可以认为是一种任务分发器,它将任务分配到Promise队列中。
var tag=true;
var p=new Promise(function(resolve,reject){
if(tag){
resolve("tag is true");
}else{
reject("tag is false");
}
})
p.then(function(result){
console.log(result);
})
.catch(function(err){
console.log(err);
})
Promise基础知识
- new Promise表示创建一个Promise实例对象
- Promise函数的第一个参数为一个回调函数,也可以称为executor。通常情况下,在这个函数中会执行发起请求,并修改结果的状态值。
- 请求结果有三种状态,分别是pending(等待中,表示还没有结果)、resolved(得到期望结果,可以继续执行)、rejected(得到错误,或者不是我们期望的结果,拒绝继续执行),请求结果默认状态为pending。
- 在executor函数中,可以分别使用resolve与reject将状态修改为对应的resolved与rejected,resolved与rejected是executor函数的两个参数,它们能够将请求结果的具体数据传递出去。
- Promise实例拥有的then方法,可用来处理当请求结果的状态变成resolved时的逻辑。then的第一个参数为一个回调函数,该函数的参数是resolve传递出来的数据。在上面的例子中,result=tag is true。
- Promise实例拥有的catch方法,可用来处理请求结果的状态变成rejected时的逻辑。catch的第一个参数为一个回调函数,该函数的参数是reject传递出来的数据。在上面的例子中,err=tag is false。
then方法可以接受两个参数,第一个参数用来处理resolved状态逻辑,第二个参数用来处理rejected状态的逻辑。
fn("abc")
.then(function(resp){
console.log(resp);
}),function(err){
console.log(err);
}
因此,catch方法与以下方法等价。
fn("abc").then(null,function(err){
cosole.log(err);
})
then方法返回的是一个Promise实例,因此then方法可以嵌套使用。在这个过程中,通过在内部函数末尾return的方式,能够将数据持续向后传递。
function fn(num){
return new Promise(function(resolve,reject){
setTimeout(function(){
if(typeof num== "number"){
resolve(num);
}else{
var err=num+"is not a number.";
reject(err);
}
},2000);
})
}
//观察语句的执行顺序
fn(20)
.then(function(result){
console.log(result); //20
return result+1;
})
.then(function(result){
cosole.log(result); //21
return result+1;
})
.then(function(result){
cosole.log(result); //22
return result+1;
})
.then(function(result){
cosole.log(result); //23
})
.then(function(result){
cosole.log(result); //undefined
})
console.log("next code");
利用Promise封装get请求的方法
var url="...";
function getJSON(url){
return new Promise(function(resolve,reject){
//利用Ajax发送一个请求
var XHR=new XMLHttpRequest();
XHR.open("GET",url,true);
XHR.send();
XHR.onreadystatechange=function(){
if(XHR.readyState==4){
if(XHR.status==200){
try{
var response=JSON.parse(XHR.responseText);
resolve(response);
}catch(e){
reject(e);
}
}else{
reject(new Error(XHR.statusText));
}
}
}
})
}
//封装之后,处理多个Ajax请求时,只需调用即可
getJSON(url).then(function(resp){
console.log(resp);
//处理数据的具体逻辑...
})
Promise.all
Promise.all接受一个Promise对象组成的数组作为参数,当这个数组中所有的Promise对象状态都变成resolved或者rejected时,它才会去调用then方法。
var url="...";
var url1="...";
function renderAll(){
return Promise.all([getJSON(url),getJSON(url1)]);
}
renderAll().then(function(value){
console.log(value);
})
Promise.race
与Promise.all相似的是,Promise.race也是一个Promise对象组成的数组作为参数,不同的是,只要当数组中的其中一个Promise状态变成resolved或者rejected时,就可以调用.then方法,其中传递给then方法的值也会有所不同。
function renderRace(){
return Promise.race([getJSON(url),getJSON(url1)]);
}
renderRace().then(function(value){
console.log(value);
})