即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。Ajax的产生主要是因为在没有异步请求的时候,网络使用的都是同步请求,设想一下你在填写银行办卡的业务表单,花费了十几分钟好不容易写完了发送同步请求到服务器提交表单,但因为同步请求的特性,在上传以及服务器响应的过程中,你无法继续你的其他业务操作,等了几分钟服务器响应给你的数据却告诉你身份证号码填写错误需要重新提交,这种时候别提多奔溃了。于是乎Ajax就有了它诞生的意义了,它可以执行异步的请求,在你填写表单的同时,数据便上传到服务器验证了,同时你可以继续你填写表单的动作,当服务器响应回数据时立马在表单的input框标红告诉你填写错误,你可以很快的更改错误的数据不需要等待服务器的响应。
在ECMAScript 5中,Ajax是依托XMLHttpRequest()实例对象来实现的,支持IE7+, Firefox, Chrome, Opera, Safari等浏览器,由于现在市面上大部分计算机浏览器都在IE8+以上,所以暂不讲述低版本IE的Ajax使用了,具体方法可自行百度 ActiveXObject()对象的使用。
首先建立实例
if(typeof window.XMLHttpRequest())
let xhr=new XMLHttpReques();
else{
throw new Error("NO XHR object available");//判断下兼容性
}
接下来就可以开始发送Ajax请求了,主要使用XMLHttpRequest()对象的open()、send()来个方法。
xhr.open(method,url,async);
xhr.send();
其中method中有两个方法‘GET’和‘POST’,两个方法中POST更加稳定且具有保密性,适合较大的数据和像密码一类需要保密的数据,而GET方法回显示在url中,以?分隔开地址,&分隔不同数据。如
上图中 type=codecamp,order=hot,paytype=all分别是三组通过GET方法传输到服务器的数据。
接下来如何获取服务器响应的数据呢?
以下是一个实例:
xhr.onreadyStatechange = function(){
if(xhr.readyState == 4){
if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
alert(xhr.responseText);
}else{
alert("Request was unsuccessful:" + xhr.status );
}
}
};
我们看下onreadyStatechange 事件w3c的解释
这样就很明确了,当readyState===4且statu状态为200-299区间时,就说明数据就成功响应了。通过responseText属性就可以获取响应数据的字符串形式了。具体的http状态码也可自行百度。
自此就完成了ES5中Ajax请求。
如果你经常是用jquery中的ajax,那你可能感受过回调地狱(callback hell)的恐惧,如果用的还是原生ajax,那可能难上加难了。而ES6中的Promise对象却很好的解决了这个问题。由于笔者刚学的ES6,对ES6的使用还不是很熟练,如果有错误的地方,还请多多包涵并告知。
首先,找过jquery使用ajax异步请求的回调例子。
$.ajax({
url: url1,
success: function(data){
$.ajax({
url: url2,
success: function(data){
$.ajax({
//...
});
}
});
}
});
如上所示,下层请求依赖于上层的请求,如果请求的阶数多了,那代码将显得十分的臃肿,可读性也很差。
而在ES6中,上述代码的实现如下:
异步请求
let http = function(url){
return new Promise((resolve,reject)=>{
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = ()=>{
if(xhr.readyState ==4 && xhr.status==200){
resolve(xhr.responseText);
}
};
xhr.open("GET",url);
xhr.send();
});
};
let exp1 = http("www.baidu.com");
exp1.then(res=>{
console.log(res);
return http('www.taobao.com');
}).then(res=>{
alert(res);
console.info(res);
})
一次性完成所有请求
let first = new Promise ((resolve,reject)=>{
$.ajax({
url:url1,
success:data=>{
if(data.Status=="success"){
resolve(data.ResultJson)//在异步操作成功时调用
}else{
reject(data.ErrMsg);//在异步操作失败时调用
}
}
})
})
let second = new Promise((resolve,reject)=>{
$ajax({
url:url2,
success: data=>{
if(...){
resolve(....)
}else{
reject(...);
}
}
})}
Promise.all([first,second]).then(([ResultJson1,ResultJson2])=>{
//这里写等这两个ajax都成功返回数据才执行的业务逻辑
})
另外还有async函数解决异步请求的方案,从语义上和语法上更优,可维护性更强。
let http = function(url){
return new Promise((resolve,reject)=>{
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = ()=>{
if(xhr.readyState ==4 && xhr.status==200){
resolve(xhr.responseText);
}
};
xhr.open("GET",url);
xhr.send();
});
};
async function func(name){
const name2 = await http(name);
console.log(name2);
const name3 = await http('taobao.com');
console.log(name3);
return http('www.hao123.com');
}
func('www.baidu.com').then(res=>{
console.log(res);
});
这样子写代码是不是清晰明了很多。
从学习前端到现在几乎都在使用Vue框架学习,所以这里怎么可能少了vue中如何使用Ajax请求呢?
首先Vue框架中不想JQuery那样封装了自己的ajax请求方法,Vue官方推荐使用axios插件,这是一个Http库,容易使用功能强大,且更加符合Vue的MVVM设计概念。
axios的特点如下:
1.从浏览器中创建 XMLHttpRequest
2.从 node.js 发出 http 请求
3.支持 Promise API
4.拦截请求和响应
5.转换请求和响应数据
6.取消请求
7.自动转换JSON数据
8.客户端支持防止CSRF/XSRF
(本小白刚开始使用,很多特性暂时还没有接触到)
由于从node.js发出的http请求,所以可以在node服务端设置代理服务器可以很好的解决跨域问题,支持Promise也更加的适应了ES6的潮流。
关于使用方法:
首先当然是安装(执行命令行)
npm i axios
//或者使用cdn:
在项目中的main.js中引用包,并付给Vue原型属性覆盖,从而修改原型链
import axios from 'axios'
Vue.prototype.$axios = axios
使用方法
//默认使用GET方法,可自行配置
this.$axios( 'www.baidu.com').then(res => {
console.log(res);
}
})
.catch(error => {
alert(error);
});
//POST方法
this.$axios.post( 'www.baidu.com',{username:“abc”,password:xxx}).then(res => {
console.log(res);
}
})
.catch(error => {
alert(error);
});
设置跨域代理服务器
在vue-cli3.0中可以很容易的设置代理服务器,先打开配置文件vue.config.js添加配置proxy(代理)
// const path = require('path');
// function resolve(dir) {
// return path.join(__dirname,dir)
// }
module.exports = {
devServer:{
proxy: {
'/api': {
target: 'http://www.baidu.com', //代理服务器请求的目标服务器地址
changeOrigin: true, //是否跨域
ws: true,
pathRewrite: {
'^/api': '' //用api代替目标服务器地址,在请求时重写
}
}
}
},
baseUrl: "./"
};
之后需要跨域访问就更改请求操作,代码如下
this.$axios( 'api/index.php?id=0').then(res => { //这里用api替换了原本的服务器地址
console.log(res);
}
})
.catch(error => {
alert(error);
});