jQuery中的ajax
jquery中的ajax
API:别人调用我我能返回东西的就叫api。向这个url发送请求服务器能返回东西的就叫api
demo:
const xhr=new XMLHttpRequest();
console.log(xhr.readyState);
xhr.open('GET','https://mock.mengxuegu.com/mock/6262c4510a65bd50bbd93eee/cgi/list');
console.log(xhr.readyState);
// 超时
xhr.onreadystatechange=function(){
console.log('==='+xhr.readyState);
if(!(/^(2|3)\d{2}$/.test(xhr.status))) return;
if(xhr.readyState===4){
console.log('===done')
console.log(xhr.responseText)
}
}
xhr.send();
console.dir(xhr);
用别人现成的封装好的库来实现——ajax
$.ajax
配置项:
contentType
传递给服务器内容的格式
这里有一个概念要区分一下,类型一般是字符串(除了字符串就是真正的流传输了)。而字符串下有好多种格式。
常用的格式:
x-www-form-urlencoded: get/post 默认遵循的都是这种格式
heades:
设置请求头
$.ajax({
url:'https://mock.mengxuegu.com/mock/6262c4510a65bd50bbd93eee/cgi/list',
method:'GET',
data:{
name:'angela',
age:18,
},
cache:false,
success:(res,status,xhr)=>{
console.log(res);
console.log(status);
console.log(xhr);
}
})
倒计时抢购案例
从服务器获取时间一定会存在误差问题:
服务器把时间给我到我拿到这个时间,中间经历的时间,就是时差
/**
* 1.首次从服务器获取时间
* 2.然后interval没间隔1秒计算时差
*/
function ajaxTime(callback){
let xhr=new XMLHttpRequest();
xhr.open('GET','https://mock.mengxuegu.com/mock/6262c4510a65bd50bbd93eee/cgi/list');
xhr.setRequestHeader('Access-Control-Expose-Headers', 'Date');
xhr.onreadystatechange=function(){
if(xhr.readyState===2){
now=new Date(xhr.getResponseHeader('Date'));
callback && callback();
}
}
xhr.send();
};
let target=new Date('2022/4/23 24:00:00')
let timer=null;
let now=null;
function computed(){
console.log(now);
let spanTime=target-now;
if(spanTime<=0){
clearInterval(timer);
timer=null;
return;
}
// 计算时分秒
let spanSecond=spanTime/1000;
console.log(spanSecond);
let hours=Math.floor(spanSecond/3600);
let minutes=Math.floor((spanSecond-hours*3600)/60);
let seconds=spanSecond%60;
document.getElementById('hour').innerHTML=hours;
document.getElementById('minute').innerHTML=minutes;
document.getElementById('second').innerHTML=seconds;
// 加一秒钟
now=new Date(+now+1000)
}
ajaxTime(()=>{
computed();
window.setInterval(computed,1000);
})
封装jquery版的ajax
封装组件、插件、类库,都是基于构造函数来做的。
所有类库/插件的封装都是基于构造函数,面向对象、类和实例、构造函数在业务开发中用不到,构造函数用于组件、类库和插件的封装上,包括框架的封装。
类的方法:
当做普通函数来执行,但是也然能创建出它的一个实例来;
绕了一圈。jQuery是类但是把它当做普通函数执行也能创建出它的实例
ajax
/**
* jquery版本
* 弊端:相互循环调用
*/
(function(){
function ajax(options){
// return ajax.prototype.fn.init(options)
return ajax.prototype.init(options)
}
ajax.prototype={
constructor:ajax,
version:1,
}
ajax.prototype.init=function init(options){}
ajax.prototype.init.prototype=ajax.prototype;
window.ajax=ajax;
})();
简单版:
/**
* 简单版本
*/
(function(){
function ajax(options){
return new init(options)
}
ajax.prototype={
constructor:ajax,
version:1,
}
function init(options){
}
init.prototype=ajax.prototype;
window.ajax=ajax;
})();
自己封装
-
配置项初始化
Object.assign 目标对象中出现的字段无条件覆盖。只要这个字段出现了,就会覆盖原来的。
那init是个类,之后所有方法都要用到options,那么需要把options挂在实例上。
封装的时候这里有一个扩展的点:函数的3种角色
(function(){
function ajax(options){
return new init(options)
}
let defaults={
url:'',
method:'GET',
data:null,
dataType:'JSON',
async:true,
cache:true,
headers:null,
timeout:null,
success:null,
error:null,
}
function init(options){
// 配置参数
this.options=Object.assign(defaults,options);
this.send();
}
ajax.prototype={
constructor:ajax,
version:1,
send(){
}
}
init.prototype=ajax.prototype;
window.ajax=ajax;
})();
-
xhr ajax请求
handleData
(function(){
function ajax(options){
return new init(options)
}
let defaults={
url:'',
method:'GET',
data:null,
dataType:'JSON',
async:true,
cache:true,
headers:null,
timeout:null,
success:null,
error:null,
}
function init(options){
// 配置参数
this.options=Object.assign(defaults,options);
this.xhr=null;
this.send();
}
let regGET=/^(GET)|(DELETE)|(HEAD)|(OPTIONS)$/i
ajax.prototype={
constructor:ajax,
version:1,
send(){
let xhr=null;
this.xhr=xhr=new XMLHttpRequest;
let {url,method,data,cache}=this.options;
// 这里的判断要扩展一下
// if(method==='GET'){
// // url+='?'
// // if(!url.endsWith('/')){
// // url+='/'
// // }
// // 尝试把这一段封装成一个方法
// if(typeof data ==='string'){
// url+=`?${data}`
// }
// if(typeof data === 'object'){
// url+=`?${Object.entries(data).map(a=>`${a[0]}=${a[1]}`).join('&')}`
// }
// }
data=this.handleData();
if(data!==null && regGET.test(method)){
url+=`${this.checkAsk(url)}${data}`;
data=null;
}
// 把cache处理掉了
if(!cache && regGET.test(method)){
url+=`${this.checkAsk(url)}_=${+new Date}`;
}
xhr.open(url,method)
},
// 这里封装得很好
handleData(){
let {data}=this.options;
if(data === null || typeof data === 'string') return data;
if(typeof data === 'object') return Object.entries(data).map(a=>`${a[0]}=${a[1]}`).join('&')
},
checkAsk(url){
return url.includes('?')?'&':'?'
}
}
init.prototype=ajax.prototype;
window.ajax=ajax;
})();
timeout/headers
判类型:Object.prototype..call(headers)
(function(){
function ajax(options){
return new init(options)
}
let defaults={
url:'',
method:'GET',
data:null,
dataType:'JSON',
async:true,
cache:true,
headers:null,
timeout:null,
success:null,
error:null,
}
function init(options){
// 配置参数
this.options=Object.assign(defaults,options);
this.xhr=null;
this.send();
}
let regGET=/^(GET)|(DELETE)|(HEAD)|(OPTIONS)$/i
ajax.prototype={
constructor:ajax,
version:1,
send(){
let xhr=null;
this.xhr=xhr=new XMLHttpRequest;
let {url,method,data,cache,timeout,headers}=this.options;
data=this.handleData();
if(data!==null && regGET.test(method)){
url+=`${this.checkAsk(url)}${data}`;
data=null;
}
// 把cache处理掉了
if(!cache && regGET.test(method)){
url+=`${this.checkAsk(url)}_=${+new Date}`;
}
xhr.open(url,method)
// 设置超时时间
timeout!==null?xhr.timeout=timeout:null;
// 设置header
if(Object.prototype.toString.call(headers)==='[object Object]'){
Object.keys(headers).forEach(key=>{
xhr.setRequestHeader(key,headers[key]);
})
}
xhr.send(data);
},
// 这里封装得很好
handleData(){
let {data}=this.options;
if(data === null || typeof data === 'string') return data;
if(typeof data === 'object') return Object.entries(data).map(a=>`${a[0]}=${a[1]}`).join('&')
},
checkAsk(url){
return url.includes('?')?'&':'?'
}
}
init.prototype=ajax.prototype;
window.ajax=ajax;
})();
success/error
(function(){
function ajax(options){
return new init(options)
}
let defaults={
url:'',
method:'GET',
data:null,
dataType:'JSON',
async:true,
cache:true,
headers:null,
timeout:null,
success:null,
error:null,
}
function init(options){
// 配置参数
this.options=Object.assign(defaults,options);
this.xhr=null;
this.send();
}
let regGET=/^(GET)|(DELETE)|(HEAD)|(OPTIONS)$/i
ajax.prototype={
constructor:ajax,
version:1,
send(){
let xhr=null;
this.xhr=xhr=new XMLHttpRequest;
let {url,method,data,cache,timeout,headers,async}=this.options;
data=this.handleData();
if(data!==null && regGET.test(method)){
url+=`${this.checkAsk(url)}${data}`;
data=null;
}
// 把cache处理掉了
if(!cache && regGET.test(method)){
url+=`${this.checkAsk(url)}_=${+new Date}`;
}
xhr.open(method,url,async)
// 设置超时时间
timeout!==null?xhr.timeout=timeout:null;
// 设置header
if(Object.prototype.toString.call(headers)==='[object Object]'){
Object.keys(headers).forEach(key=>{
xhr.setRequestHeader(key,headers[key]);
})
}
let {success,error,dataType}=this.options;
xhr.onreadystatechange=()=>{
let { readyState,status,statusText,responseText,responseXML}=xhr;
if(readyState===4 && /^(2|3)\d{2}$/.test(status)){
switch(dataType.toUpperCase()){
case 'JSON':
responseText=JSON.parse(responseText);
break;
case 'XML':
responseText=responseXML;
break;
}
success && success(responseText,statusText,xhr);
return;
}
error && error(statusText,xhr);
}
xhr.send(data);
},
// 这里封装得很好
handleData(){
let {data}=this.options;
if(data === null || typeof data === 'string') return data;
if(typeof data === 'object') return Object.entries(data).map(a=>`${a[0]}=${a[1]}`).join('&')
},
checkAsk(url){
return url.includes('?')?'&':'?'
}
}
init.prototype=ajax.prototype;
window.ajax=ajax;
})();
ajax({
url:'https://mock.mengxuegu.com/mock/6262c4510a65bd50bbd93eee/cgi/list',
success:(obj)=>{
console.log('obj===');
console.log(obj);
},
headers:{
a:'a',
},
data:{
name:'a',
}
})
(function(){
function ajax(options){
return new init(options)
}
let defaults={
url:'',
method:'GET',
data:null,
dataType:'JSON',
async:true,
cache:true,
headers:null,
timeout:null,
success:null,
error:null,
}
function init(options){
// 配置参数
this.options=Object.assign(defaults,options);
this.xhr=null;
this.send();
}
let regGET=/^(GET)|(DELETE)|(HEAD)|(OPTIONS)$/i
ajax.prototype={
constructor:ajax,
version:1,
send(){
let xhr=null;
this.xhr=xhr=new XMLHttpRequest;
let {url,method,data,cache,timeout,headers,async}=this.options;
data=this.handleData();
if(data!==null && regGET.test(method)){
url+=`${this.checkAsk(url)}${data}`;
data=null;
}
// 把cache处理掉了
if(!cache && regGET.test(method)){
url+=`${this.checkAsk(url)}_=${+new Date}`;
}
xhr.open(method,url,async)
// 设置超时时间
timeout!==null?xhr.timeout=timeout:null;
// 设置header
if(Object.prototype.toString.call(headers)==='[object Object]'){
Object.keys(headers).forEach(key=>{
xhr.setRequestHeader(key,headers[key]);
})
}
let {success,error,dataType}=this.options;
xhr.onreadystatechange=()=>{
let { readyState,status,statusText,responseText,responseXML}=xhr;
if(readyState===4 && /^(2|3)\d{2}$/.test(status)){
switch(dataType.toUpperCase()){
case 'JSON':
responseText=JSON.parse(responseText);
break;
case 'XML':
responseText=responseXML;
break;
}
success && success(responseText,statusText,xhr);
return;
}
error && error(statusText,xhr);
}
xhr.send(data);
},
// 这里封装得很好
handleData(){
let {data}=this.options;
if(data === null || typeof data === 'string') return data;
if(typeof data === 'object') return Object.entries(data).map(a=>`${a[0]}=${a[1]}`).join('&')
},
checkAsk(url){
return url.includes('?')?'&':'?'
}
}
init.prototype=ajax.prototype;
window.ajax=ajax;
})();
ajax({
url:'https://mock.mengxuegu.com/mock/6262c4510a65bd50bbd93eee/cgi/list',
success:(obj)=>{
console.log('obj===');
console.log(obj);
},
headers:{
a:'a',
},
data:{
name:'a',
}
})
请求头Content-Type - 简书
HTTP请求头中的Content-Type类型 - 百度文库
|