什么是AJAX:
AJAX 并非编程语言,仅仅组合了
浏览器内建的 XMLHttpRequest 对象(从 web 服务器请求数据)
JavaScript 和 HTML DOM(显示或使用数据)
JAX 如何工作:
网页中发生一个事件(页面加载、按钮点击)
由 JavaScript 创建 XMLHttpRequest 对象
XMLHttpRequest 对象向 web 服务器发送请求
服务器处理该请求
服务器将响应发送回网页
由 JavaScript 读取响应
由 JavaScript 执行正确的动作(比如更新页面
AJAX - XMLHttpRequest 对象:
//兼容
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
Ajax 的核心是 XMLHttpRequest 对象。
所有现代浏览器都支持 XMLHttpRequest 对象。
XMLHttpRequest 对象用于同幕后服务器交换数据。这意味着可以更新网页的部分,而不需要重新加载整个页面
创建 XMLHttpRequest 对象
语法:
//兼容
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
向服务器发送请求
xhttp.open("GET", "ajax_info.txt", true);
xhttp.send();
方法:
open(method, url, async)
method:请求的类型:GET 还是 POST
url:服务器(文件)位置
async:true(异步)或 false(同步)
send()
向服务器发送请求(用于 GET)
send(string)
向服务器发送请求(用于 POST)
get比post更简单更快,可用于大多数情况下
post使用的场景:
缓存文件不是选项(更新服务器上的文件或数据库)
向服务器发送大量数据(POST 无大小限制)
发送用户输入(可包含未知字符),POST 比 GET 更强大更安全
setRequestHeader(key, value) 设置请求头
getResponseHeader(key) 获取响应头
属性:
readyState xhr的状态码 4 响应体接收完毕
status 获取状态码
responseText 获取响应体,文本格式
responseXML 获取响应体,xml格式
onreadtstatechange 事件,当xhr.readyState属性发生改变触发
onload 事件,响应接收完毕
实例:
GET请求:
//无携带参数请求:
xhttp.open("GET", "demo_get.asp", true);
xhttp.send();
//请向 URL 添加一个唯一的 ID
xhttp.open("GET", "demo_get.asp?t=" + Math.random(), true);
xhttp.send();
//请向 URL 添加这些信息
xhttp.open("GET", "demo_get2.asp?fname=Bill&lname=Gates", true);
xhttp.send();
document.getElementById('btn').onclick = function () {
// 创建xhr对象
let xhr = new XMLHttpRequest()
// 调用open方法,设置请求方式和URL
xhr.open('GET', 'http://127.0.0.1:3000/search')
// 调用send方法,发送
xhr.send()
// 当请求响应过程结束了(调用了xhr.onload事件),通过responseText属性接收服务器返回的数据
xhr.onload = function () {
console.log(xhr.responseText)
}
}
POST请求
//无携带参数请求:
xhttp.open("POST", "demo_post.asp", true);
xhttp.send();
//请求头HTTP有携带参数请求:通过 setRequestHeader() 添加一个 HTTP 头部
xhttp.open("POST", "ajax_test.asp", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send("fname=Bill&lname=Gates");
document.getElementById('btn').onclick = function () {
// 创建xhr对象
let xhr=new XMLHttpRequest()
// 调用open方法,设置请求方式和URL
xhr.open('POST', 'http://127.0.0.1:3000/search')
// 调用setRequestHeader( )方法,设置header头,指定content-type
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
// 调用send方法,发送
xhr.send('x=11111')
// 当请求响应完毕,接收服务器返回的数据
xhr.onreadystatechange=function(){
if (xhr.readyState===4 || xhr.status===200) {
console.log(xhr.responseText);
}
}
}
AJAX - 服务器响应
onreadystatechange:定义了当 readyState 属性发生改变时所调用的函数。
readyState:保存了 XMLHttpRequest 的状态。
0: 请求未初始化
1: 服务器连接已建立
2: 请求已接收
3: 正在处理请求
4: 请求已完成且响应已就绪
status:存有 XMLHttpRequest 对象的状态
200: "OK"
403: "Forbidden"
404: "Page not found"
statusText:存有 XMLHttpRequest 对象的状态
返回状态文本(例如 "OK" 或 "Not Found")
http请求常见的status状态码:
404:(Not Found)服务器无法找到请求的页面或资源。
此类报错首先考虑我们的接口写的时候正确。(可以借用postman来测试,postman的使用详情可见另外一篇博客内容)
其次可以检查资源的路径是否出错。
405:(Method Not Allowed )方法不允许,方法禁用。
一般出现在servlet中比较常见.就是自己的service函数写错了。
方法名称写错,方法参数类型与标准不一致。
方法异常、返回值类型与标准不一致。(这一般是前台的问题,我们的解决方案是:把post请求换成get请求)
500 :(Internal Server Error) 服务器内部错误,不能完成客户的请求。
500报错一般是后端服务器问题,但也不排除前端出错,例如后台报序列化错误,可能是因为前端没有设置content-Type=application/json。
重要的是要查看自己写的后端业务逻辑代码有没有问题,根据报错提示查找bug。
常见的错误位置:NullPointException,据库中提取的数据没有提取到而给另一个对象,传递了空值或注入某个对象,过程中出现空值.,没有正确获取到对象的而出现异常。
501:( Not Implemented)尚未实施,或请求格式错误。
一般考虑我们前端写的ajax中的type:"post/get"是否出错或者from表单中的method:"post/get"是否书写错误。
状态码大致含义:
1xx:临时响应(Informational),需要请求者继续执行操作的状态代码,表示服务器正在接受请求。
2xx:成功状态码(Success),已成功接受客户端请求。
3xx:重定向状态码(Redirection),需要客户端做进一步操作来完成请求。
4xx:客户端错误(Client Error),客户端请求出错导致服务端无法正常完成请求。(404 )
5xx:服务端错误(Server Error),服务器出错未能成功处理服务端请求。
axios
特点:
从浏览器中创建 XMLHttpRequests
从 node.js 创建 http 请求
支持 Promise API
拦截请求和响应
转换请求数据和响应数据
取消请求
自动转换 JSON 数据
使用axios
利用npm安装:npm install axios
发送get和post
post请求的时候参数通过data进行传递get请求的时候参数通过params进行传递
get 请求
方法一:
axios({
// 默认请求方式为get
method: 'get',
url: 'api',
// 传递参数
params: {
key: value
},
// 设置请求头信息
headers: {
key: value
}
responseType: 'json'
}).then((response) => {
// 请求成功
let res = response.data;
console.log(res);
}).catch((error) => {
// 请求失败,
console.log(error);
});
方法二:
axios.get("api", {
// 传递参数
params: {
key: value
},
// 设置请求头信息,可以传递空值
headers: {
key: value
}
}).then((response) => {
// 请求成功
let res = response.data;
console.log(res);
}).catch(error => {
// 请求失败,
console.log(error);
});
post 请求
方法一
// 注:post请求方法有的要求参数格式为formdata格式,此时需要借助 Qs.stringify()方法将对象转换为字符串
let obj = qs.stringify({
key: value
});
axios({
method: 'post',
url: 'api',
// 传递参数
data: obj,
// 设置请求头信息
headers: {
key: value
},
responseType: 'json'
}).then((response )=> {
// 请求成功
let res = response.data;
console.log(res);
}).catch(error => {
// 请求失败,
console.log(error);
});
方法二:
let data = {
key: value
},
headers = {
USERID: "",
TOKEN: ""
};
// 若无headers信息时,可传空对象占用参数位置
axios.post("api", qs.stringify(data), {
headers
}
}).then((response) => {
// 请求成功
let res = response.data;
console.log(res);
}).catch((error) => {
// 请求失败,
console.log(error);
});
axios 的全局配置
首先通过axios.defaults.baseURL抽离出公共的部分,在各部分请求地址时可以省去公共的部分,适用于项目中所有的axios请求。
//baseURL的举例,还可以配置headers等
<script>
axios.defaults.baseURL="http://localhost:8888/";
axios.defaults.timeout=4000;
axios.get("info").then(res=>{
console.log(res);
})
</script>
vue项目中全局配置axios
创建文件夹:src->axios->index.js,里面对axios进行一系列封装,包括添加拦截器和封装请求。
// 导入安装的axios
import axios from 'axios'
// 导入elementUI错误消息提示
import { Message } from 'element-ui'
// 导入路由
import router from '../router/router'
// 创建axios请求实例,并暴
const myaxios = axios.create({
baseURL: 'http://localhost:8080',//接口基础地址
timeout: 1000,//允许延迟时长
headers: { 'Content-Type':'application/x-www-form-urlencoded' }
//post请求头部,默认将请求数据作json向后端传送;多数情况后端希望是"x-www-form-urlencoded"格式。大家视实际情况而变。
});
// 添加请求拦截器
myaxios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
// 一般是添加token再发送
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
myaxios.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
// 如果业务逻辑错误
if (response.status || response.status === 200) {
// 如果返回数据中code=500,或者是未登录401,权限错误403
if (response.data.code === 500 || response.data.code === 401 || response.data.code === 403) {
Message.error({ message: response.data.message });
return;
}
// 如果是其他
if (response.data.message) {
Message.success({ message: response.data.message });
}
}
return response.data;
}, function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
if (error.response.data.code === 504 || error.response.data.code === 404) {
Message.error({ message: '服务器被吃了( •̀ ω •́ )' });
} else if (error.response.data.code === 403) {
Message.error({ message: '权限不足,请联系管理员' });
} else if (error.response.data.code === 401) {
Message.error({ message: '尚未登录,请登录!' });
//跳往登录界面
router.push('/');
} else {
if (error.response.data.message) {
Message.error({ message: error.response.data.message });
}else{
Message.error({ message:'未知错误去( •̀ ω •́ )✧'});
}
}
return;
});
//暴露接口
export default myaxios;
在main.js文件中全局引入配置好的myaxios。这样你在任何一个组件里都可以使用this.$axios.get()、this.$axiso.post() 等等直接向服务器发送请求。
import Vue from 'vue'
import App from './App.vue'
import myaxios from './utils/axios'
// 关闭vue的提示
Vue.config.productionTip = false
// 给全局Vue实例对象添加axios属性
Vue.prototype.$axios = myaxios;
new Vue({
render: h => h(App)
}).$mount('#app')