这是我参与「第四届青训营 」笔记创作活动的第3天
(三)Promise封装Ajax
🟢先看看单独的Ajax
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
//do something
}
}
}
xhr.open('GET',"https://api.apiopen.top/GetJoke");
xhr.responseType = 'json';
xhr.send();
如果修改了Ajax中open的地址为错误的地址后,xhr的readyState和status都会变化吗?
-
xhr.readyState 依旧等于 4,只不过之前返回的是get到的资源,而现在返回的是没有get的错误信息。(无论地址对不对服务器都会有反应)
-
如果将
https://api.apiopen.top/GetJoke改成https://api.apiopen.top/GetJoke2那status会变成404。联系上服务器了,但是服务器没有所需要的资源。如果将
https://api.apiopen.top/GetJoke改成https://api2.apiopen.top/GetJoke那status会 变成0。根本没有联系上服务器
所以,我们不能仅仅通过readyState==4就判断已经加载完毕,因为这有可能是成功的资源加载完毕,也有可能是错误的信息加载完毕。
从上面我们可以得到何时调用resolve函数,何时调用reject函数👇🏻
📌数据请求成功 ⇒ xhr.readyState = 4 && xhr.status = 200 ⇒ 切换成fulfilled状态 ⇒ 调用resolve函数,传值为xhr.reponse。
📌数据请求失败 ⇒ xhr.readyState = 4 但是xhr.status != 200 ⇒
切换为rejected状态 ⇒ 调用reject函数,传值为“请求出错”
🟢promise配合Ajax使用
var p = new Promise((resolve,rejected)=>{
//开启一个异步任务
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
resolve(xhr.response);
}else{
reject("请求失败");
}
}
}
xhr.open('GET',"https://api.apiopen.top/GetJoke");
xhr.responseType = 'json';
xhr.send();
})
p.then(
(value)=>{console.log('成功了',value);},
(reason)=>{console.log('失败了',reason);}
)
🟢封装Ajax为一个函数
上面Promise配合Ajax的示例中,请求的地址是写死的,参数也没带,封装一个通用性更强的函数(可以传入请求地址和参数的),名为sendAjax
📌要求:对get请求进行封装。接收两个参数,url(请求地址)和data(请求参数)。返回值为一个Promise示例。
⇒ 我传入的请求参数是参数对象,而url后跟的请求参数的格式是query。所以要转化一下。
即:{page:1,count:2,type:video}转化为page=1&count=2&type=video
function sendAjax (url, data){
var p = new Promise((resolve,reject)=>{
//示例xhr
const xhr = new XMLHttpRequest();
//绑定监听
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status >= 200 && xhr.status < 300){
resolve(xhr.response);
}else{
reject("请求失败");
}
}
}
//参数对象的转化
var str = '';
for(let key in data){
str+='${key}=${data[key]}&'
}
str = str.slice(0,-1); //去掉最后一个&
xhr.open('GET',url + '?'+ str);
xhr.responseType = 'json';
xhr.send();z
})
return p;
}
在下方调用函数:
const p =sendAjax("https://api.apiopen.top/GetJoke",{page:1,count:2,type:video});
console.log(p);
输出结果为:Promise<pending>,为什么不是Promise<fulfilled>呢?明明已经请求成功了啊
原因:请求成功后改变状态的回调函数是异步的,必须等到主线程执行完毕后才能执行,所以只有当console.log(p);执行完后才会修改promise实例对象的状态。
实际上,输出promise实例是不规范的,应该用.then方法指定成功和失败的回调。
应该修改为:
const p =sendAjax("https://api.apiopen.top/GetJoke",{page:1,count:2,type:video});
p.then(
(value)=>{console.log('成功了',value);},
(reason)=>{console.log('失败了',reason);}
);