XMLHttpRequest 的简单记录。
写过无数次的 $.ajax ,然而jQuery 没落了。当前比较流行的是 axios 库,和 $.ajax 同是基于 XMLHttpRequest,本章节简单记录 XMLHttpRequest 和相关有用的代码 ,以便用时方便查找。也许不久后,XMLHttpRequest 也将过时,被 fetch 取代。至于 ajax / axios / fetch 不多赘述,相关的 api 比较类似并且很好查。
一 XMLHttpRequest
XMLHttpRequest ,ajax (Asynchronous JavaScript and XML) 发出 HTTP 请求、进行浏览器和服务器通信的原生对象。
/* 1. 创建实例 */
var xhr = new XMLHttpRequest();
/* 2. 监听请求是否成功 */
xhr.onload = function() {
console.log('请求成功');
}
/**
* 3. 发出 HTTP 请求: open 启动请求; send 发送请求。
* open 参数:open(method,url,async)
* method: 请求方法,GET, POST 等
* url:发送请求的地址
* async:是否异步,true 表示异步,false 表示同步。
*/
// GET 请求参数直接写在url后面,如 http://localhost/hello?name=jack&age=20
xhr.open('GET', 'http://localhost/hello?name=jack&age=20', true);
xhr.send();
// POST 需要向请求添加 http 头: setRequestHeader(header,value), header: 规定头的名称,value: 规定头的值
// 请求参数要写在 send() 方法内,send() 方法接收一个 String 类型的参数
xhr.open('POST', 'http://localhost/hello', true);
// 一般格式参数
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded")
xhr.send('name=jack&age=20');
// json 格式参数, 通过 JSON.stringify() 转成字符串
xhr.setRequestHeader("Content-type","application/json")
xhr.send(JSON.stringify({"name":"jack","age":20}));
/**
* 4. 响应
* 反应响应状态的三个属性:
* readyState:0-请求未初始化;1-已经调用open;2-发送,已经调用send;3-请求处理中;4-请求已完成,且响应已就绪
* onreadystatechange:事件,每当 readyState 改变时,就会调用该函数。
* status:200-成功;404-未找到地址
* 响应的内容:
* responseText: 返回字符串形式的内容
* responseXML:返回 xml 形式的内容
*/
xhr.onreadystatechange=function() {
if (xhr.readyState==4 && xmlhttp.status==200) {
console.log(xhr.responseText);
}
}
/* 终止请求 onabort ie10+ */
xhr.abort();
// 终止请求后可以触发的事件
xhr.onabort = funciton(){}
/* 超时 超过时间后没有返回,请求会自动终止, 触发 ontimeout 事件。ontimeout ie10+。*/
xhr.timeout = 1000;
xhr.ontimeout = function(){}
虽然 MDN 给出了 timeout 在各浏览器中的兼容性,但《javascript权威指南》和《javascript高级程序设计》对它目前的兼容性很不乐观,以下是权威指南给的一段自定义实现超时的代码:
function timedGetText(url, timeout, callback){
var request = new XMLHttpRequest();
var timedout = false;
var timer = setTimeout(function(){
timedout = true;
request.abort();
}, timeout);
request.open('GET', url);
request.onreadystatechange = function(){
if(!request.readyState !== 4) return;
if(timedout) return;
clearTimeout(timer);
if(request.status === 200){
callback(request.responseText);
}
};
request.send(null);
}
二 axios
如下是一段封装好的 axios,并不是十分好,不过也许方便后续使用。如需更改,仍要参考官网,官网很详尽。
import axios from 'axios';
import Qs from 'qs';
// 请求失败报错列表
const errorStatusMap = new Map([
[400, '参数不合法'],
[401, '未授权,请登录'],
[403, '拒绝访问'],
[404, '资源不存在'],
[408, '请求超时'],
[500, '服务器内部错误'],
[501, '服务未实现'],
[502, '网关错误'],
[503, '服务不可用'],
[504, '网关超时'],
[505, 'HTTP版本不受支持']
]);
// create an axios instance
export const service = axios.create({
baseURL: '/',
// 如果请求超过 `timeout` 的时间,请求将被中断
timeout: 1000,
transformRequest(data, headers) {
if (headers.tp === '1') {
return Qs.stringify(data, {
allowDots: true,
arrayFormat: 'indices'
});
}
if (headers['Content-Type'] !== 'multipart/form-data') {
return Qs.stringify(data, {
allowDots: true,
arrayFormat: 'brackets'
});
}
return data;
},
// 负责params 序列化函数
paramsSerializer(params) {
return Qs.stringify(params);
}
});
// 引入本地json文件
export const getJson = (url) =>
new Promise((resolve, reject) => {
axios({
method: 'get',
url,
dataType: 'json',
crossDomain: true,
cache: false
})
.then((res) => {
resolve(res);
})
.catch((error) => {
reject(error);
});
});
// 请求拦截
service.interceptors.request.use(
(config) => config,
(error) => (console.log(error))
);
// 响应拦截
service.interceptors.response.use(
(response) => {
if (response.status === 200) {
const { data } = response;
// dosomething
return data
}
return Promise.reject(response);
},
(error) => {
if (error && error.response) {
error.message = errorStatusMap.get(error.response.status) ? errorStatusMap.get(error.response.status) : error;
} else if (error && error.request) {
if (error.request.readyState === 4 && error.request.status === 0) {
error.message = '接口响应超时';
}
}
return Promise.reject(error.message);
}
);
const request = {
post(url, data, config) {
return service.post(url, data, config);
},
get(url, params, config) {
return service.get(url, { params, config });
},
getJson(url) {
return getJson(url);
},
upload(url, data, config) {
return service.post(url, data, config);
}
};
export default request;