(ps:一直使用的时jquery封装好的ajax,没有对此深究过,直到看到了一些面试题,才发现对此一无所知。)
参考文档:https://segmentfault.com/a/1190000004322487
简单使用:
//get
var ajax = new XMLHttpRequest();
ajax.open('get','./1.php?name=233');
ajax.send();
ajax.onreadystatechange = function(){
if(ajax.readyState == 4 && ajax.status == 200){
console.log(ajax.responseText);
}
}
// post
var xhr = new XMLHttpRequest();
xhr.open('post', '1.php' );
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.send('name=fox&age=18');
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.responseText);
}
};
简单封装:
function ajax(opt){
opt = opt || {};
opt.method = opt.method.toUpperCase() || 'POST';
opt.url = opt.url || '';
opt.async = opt.async || true;
opt.data = opt.data || null;
opt.success = opt.success || function(){};
var xmlHttp = null;
if (XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
} else {
xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');
}
var params = [];
for(var key in opt.data){ params.push(key+"="+opt.data[key]); }
var postData = params.join("&");
if(opt.method === 'POST'){
xmlHttp.open(opt.method,opt.url,opt.async);
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
xmlHttp.send(postData);
} else {
xmlHttp.open(opt.method,opt.url+'?'+postData,opt.async);
xmlHttp.send(null);
}
xmlHttp.onreadystatechange = function(){
if(xmlHttp.readyState == 4 && xmlHttp.status === 200){
opt.success(xmlHttp.responseText);
}
}
}
// 使用
ajax({
method: 'post',
url: './1.php',
data: {
name: "prayer",
age: 15
},
success: function(response){
console.log(response);
}
});
1.php代码
<?php
/**
* @Author: anchen
* @Date: 2018-07-20 17:38:33
* @Last Modified by: anchen
* @Last Modified time: 2018-07-20 18:01:07
*/
if(isset($_GET['name'])){
echo 'hello '.$_GET['name'];
} else if ($_POST['name']&&$_POST['age']) {
echo 'hello '.$_POST['name'].' you are '.$_POST['age'];
} else {
echo 'nobody';
}
如果你想要更详细的兼容,可以参考
function createXHR(){
if(typeof XMLHttpRequest != "undefined"){
createXHR = function(){
return new XMLHttpRequest();
}
} else if (typeof ActiveXObject != "undefined"){
createXHR = function(){
if(typeof arguments.callee.activeXString != "string"){
var verions = ["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"],
i,len;
for(i=0,len=verions.length;i<len;i++){
try{
new ActiveXObject(verions[i]);
arguments.callee.activeXString = verions[i];
break;
} catch(ex){
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
};
} else {
createXHR = function(){
throw new Error("No XHR object available");
}
}
}
promise封装
/**
* ajax函数,返回一个promise对象
* @param{object} opt 参数设置,支持的参数如下
* url: url地址,默认空
* method: 请求方法,默认GET
* async: 是否异步,默认true
* data: 发送的数据,默认为空
* dataType: 接收的数据的类型,默认text
* iscors: 是否跨域携带cookie信息
* @return{promise}
* 该函数注册xmlHttp.onloadend回调函数,判断xmlHttp.status是否属于 [200,300)&&304
* 如果属于则promise引发resolve状态,允许拿到xmlHttp对象
* 如果不属于,或已经引发了ontimeout,onabort,则引发reject状态,允许拿到xmlHttp对象
* @reject
* 返回一个对象,包含
* errorType: 错误类型
* abort_error: xmlHttp对象调用abort函数
* timeout_error: 请求超时
* onerror: xmlHttp对象出发了onerror事件
* send_error: 发送请求出现错误
* status_error: 响应状态不属于(200,300)&&304
*/
function ajax(opt){
//设置参数默认值
opt = opt || {};
opt.url = opt.url || '';
opt.method = opt.method.toUpperCase() || 'POST';
opt.async = opt.async || true;
opt.data = opt.data || null;
opt.timeout = opt.timeout || 0;
opt.dataType = opt.dataType || 'text';
opt.iscors = opt.iscors || false;
//设置钩子函数默认值
//处理data参数
if(opt.data !== null){
var params = [];
for(var key in opt.data){ params.push(key+"="+opt.data[key]); }
opt.data = params.join("&");
}
//新建xmlHttp对象
var xmlHttp = null;
if (XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
} else {
xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');
}
//返回一个Promise对象
return new Promise(function(resolve,reject){
if(opt.method === 'POST'){
xmlHttp.open(opt.method,opt.url,opt.async);
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
} else {
xmlHttp.open(opt.method,opt.url+'?'+opt.data,opt.async);
}
xmlHttp.timeout = opt.timeout;//设置超时
xmlHttp.responseType = opt.dataType;//设置接受的数据类型
//追踪Ajsx请求的当前状态,钩子函数
xmlHttp.onreadystatechange = function(){
switch(xmlHttp.readyState){
case 0: //UNSET
console.group("xmlHttp对象成功构造");
console.log(xmlHttp);
console.groupEnd();
break;
case 1: //OPENED
console.group("open()方法已被调用");
console.log(xmlHttp);
console.groupEnd();
break;
case 2: //HEADERS_RECEIVED
console.group("响应头和响应状态已经返回");
console.log(xmlHttp);
console.groupEnd();
break;
case 3: //LOADING
console.group("响应体正在被下载,responce可能有数据了");
console.log(xmlHttp);
console.groupEnd();
break;
case 4: //DONE
console.group("数据传输结束,无论成败");
console.log(xmlHttp);
console.groupEnd();
break;
}
}
xmlHttp.onloadstart = function(){
console.group("xmlHttp触发send()");
console.log(xmlHttp);
console.groupEnd();
};
xmlHttp.onprogress = function(){
console.group("xmlHttp下载阶段,readystate=3时,50ms触发一次");
console.log(xmlHttp);
console.groupEnd();
};
xmlHttp.upload.onprogress = function(){
console.group("xmlHttp触发send()后,readystate=2之前的上传阶段,50ms触发一次");
console.log(xmlHttp);
console.groupEnd();
};
//成功事件
xmlHttp.onload = function(){
if(xmlHttp.status >=200 && xmlHttp.status < 300 || xmlHttp.status == 304){
resolve(xmlHttp);
} else {
//resolve other status,like 404
reject({
errorType: 'status_error',
xmlHttp: xmlHttp
})
}
};
xmlHttp.onloadend = function(){
console.group("请求结束,无论成败");
console.log(xmlHttp);
console.groupEnd();
};
xmlHttp.onabort = function(){
reject(new Error({
errorType: 'abort_error',
xmlHttp: xmlHttp
}));
};
xmlHttp.ontimeout = function(){
reject({
errorType: 'timeout_error',
xmlHttp: xmlHttp
});
};
xmlHttp.onerror = function(){
reject({
errorType: 'onerror',
xmlHttp: xmlHttp
})
};
//处理网络错误
try {
xmlHttp.send(opt.data);
} catch(e){
reject({
errorType: 'send_error',
error: e
});
}
});
}
//使用示例
ajax({
method: 'post',
url: './1.php',
data: {
name: "prayer",
age: 15
},
timeout: 200
}).then(function(xmlHttp){
//do something witch success
console.log('成功获取数据: ',xmlHttp.response);
}).catch(function(e){
//do something witch error
console.error('error: ',e);
})
来看看整个过程发生了那些事情
如果有什么不明白的地方,可以私信我>.<