AJAX(Ci)
axios库
说明
一种promise对象
1.使用步骤
引入axios.js
使用axios函数
获取数据,并做后续处理
2.语法
<body>
//引入axios.js
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
axios({请求配置项}).then(result=>{请求成功后运行}).catch(error =>{请求失败后运行})
</script>
</body>
3.详解
请求配置项
语法
axios({ 请求配置项1,//逗号隔开 请求配置项2 })
配置项类别
URL地址
语法
url:'目标资源地址'
请求方法(不写默认GET)//不分大小写
语法:
method:'get'
请求方法
查询参数
作用:带参查询
语法:
params:{参数名1:值1,参数名2:值2}
提交数据
语法:
data:{参数名:值}
请求体
语法:
headers:{参数名:值}
.then
语法
.then(result =>{处理数据})
获取数据
result.data
包含了服务器响应的内容//一个对象result.data.属性名
访问这个属性//eg:list
.catch
语法
.catch(error =>{处理错误})
获取数据
error.response
包含了服务器响应的内容//一个对象
4.错误处理
浏览器错误处理
axios错误处理
查看:控制台-Uncaught (in promise)-response-data//错误信息
获取:
.catch(error =>{error.response})
显示:弹窗提醒用户
5.图片上传
语法
//绑定change事件
document.querySelector('input').addEventListener('change',(e)={
//获取图片文件对象
console.log(e.target.files[0])
//创建FormData对象
const fd=new FormData()
//使用FormData携带图片文件
fd.append(参数名,值)
//参数名:文档说明
//值:图片文件
//axios配置项中上传(文档指定位置)
data:fd
})
url
概念:统一资源定位符,简称网址,用于访问网络上的资源
资源分类
网页资源
图片资源
数据资源
组成
协议
指定传输格式
域名(必需)
服务器地址
资源路径
标记资源在服务器下的具体位置
查询参数
定义:带参查询
语法:
?参数名1=值1&参数名2=值2
样例
http://XXX.com/xxx/xxx?参数名1=值1&参数名2=值2
实现:在axios里面用params实现
协议
HTTP协议
说明:超文本传输协议,规定浏览器和服务器之间传输数据的格式
请求报文
定义:浏览器按照HTTP协议要求的格式,发送给服务器的内容
组成:
请求行
请求方法
URL
协议
请求头
以键值对的格式携带的附加信息
比如:Content-Type(内容类型)
请求体
发送的资源
查看
开发者-网络-Fetch/XHR-操作对象-请求标头//请求头
开发者-网络-Fetch/XHR-操作对象-负载//请求体
错误排查
说明:通过请求报文排查
响应报文
定义:服务器按照HTTP协议要求的格式,返回给浏览器的内容
组成:
响应行(状态行)
协议
HTTP响应状态代码
状态信息
响应头
以键值对的格式携带的附加信息
比如:Content-Type(内容类型)
空行
分隔响应头和请求体
请求体
发送的资源
查看
开发者-网络-Fetch/XHR-操作对象-响应标头//响应行
开发者-网络-Fetch/XHR-操作对象-响应//响应体
HTTP响应状态码
定义:用来表明请求是否成功完成
状态码
eg:404(服务器找不到资源)
https
接口文档
接口文档
描述接口的文章
接口
使用AJAX和服务器通讯时,使用的URL,请求方法,以及参数
结构
url
请求参数
位置
head参数//请求头
位置:axios配置项的headers:{}里面
body参数//请求体
位置:axios配置项的data:{}里面
path路径传参
位置:axios配置项的url改成模板字符串,规定位置写参数
query查询参数
位置:axios配置项的params:{}里面
格式
json//json字符串
form-data//表单数据对象
form-serialize插件
作用
快速收集表单元素是的值
引入
粘贴以下代码至单独js文件
script引入该文件
// get successful control from form and assemble into object
// http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2
// types which indicate a submit action and are not successful controls
// these will be ignored
var k_r_submitter = /^(?:submit|button|image|reset|file)$/i;
// node names which could be successful controls
var k_r_success_contrls = /^(?:input|select|textarea|keygen)/i;
// Matches bracket notation.
var brackets = /(\[[^\[\]]*\])/g;
// serializes form fields
// @param form MUST be an HTMLForm element
// @param options is an optional argument to configure the serialization. Default output
// with no options specified is a url encoded string
// - hash: [true | false] Configure the output type. If true, the output will
// be a js object.
// - serializer: [function] Optional serializer function to override the default one.
// The function takes 3 arguments (result, key, value) and should return new result
// hash and url encoded str serializers are provided with this module
// - disabled: [true | false]. If true serialize disabled fields.
// - empty: [true | false]. If true serialize empty fields
function serialize(form, options) {
if (typeof options != 'object') {
options = { hash: !!options };
}
else if (options.hash === undefined) {
options.hash = true;
}
var result = (options.hash) ? {} : '';
var serializer = options.serializer || ((options.hash) ? hash_serializer : str_serialize);
var elements = form && form.elements ? form.elements : [];
//Object store each radio and set if it's empty or not
var radio_store = Object.create(null);
for (var i=0 ; i<elements.length ; ++i) {
var element = elements[i];
// ingore disabled fields
if ((!options.disabled && element.disabled) || !element.name) {
continue;
}
// ignore anyhting that is not considered a success field
if (!k_r_success_contrls.test(element.nodeName) ||
k_r_submitter.test(element.type)) {
continue;
}
var key = element.name;
var val = element.value;
// we can't just use element.value for checkboxes cause some browsers lie to us
// they say "on" for value when the box isn't checked
if ((element.type === 'checkbox' || element.type === 'radio') && !element.checked) {
val = undefined;
}
// If we want empty elements
if (options.empty) {
// for checkbox
if (element.type === 'checkbox' && !element.checked) {
val = '';
}
// for radio
if (element.type === 'radio') {
if (!radio_store[element.name] && !element.checked) {
radio_store[element.name] = false;
}
else if (element.checked) {
radio_store[element.name] = true;
}
}
// if options empty is true, continue only if its radio
if (val undefined && element.type 'radio') {
continue;
}
}
else {
// value-less fields are ignored unless options.empty is true
if (!val) {
continue;
}
}
// multi select boxes
if (element.type === 'select-multiple') {
val = [];
var selectOptions = element.options;
var isSelectedOptions = false;
for (var j=0 ; j<selectOptions.length ; ++j) {
var option = selectOptions[j];
var allowedEmpty = options.empty && !option.value;
var hasValue = (option.value || allowedEmpty);
if (option.selected && hasValue) {
isSelectedOptions = true;
// If using a hash serializer be sure to add the
// correct notation for an array in the multi-select
// context. Here the name attribute on the select element
// might be missing the trailing bracket pair. Both names
// "foo" and "foo[]" should be arrays.
if (options.hash && key.slice(key.length - 2) !== '[]') {
result = serializer(result, key + '[]', option.value);
}
else {
result = serializer(result, key, option.value);
}
}
}
// Serialize if no selected options and options.empty is true
if (!isSelectedOptions && options.empty) {
result = serializer(result, key, '');
}
continue;
}
result = serializer(result, key, val);
}
// Check for all empty radio buttons and serialize them with key=""
if (options.empty) {
for (var key in radio_store) {
if (!radio_store[key]) {
result = serializer(result, key, '');
}
}
}
return result;
}
function parse_keys(string) {
var keys = [];
var prefix = /^([^\[\]]*)/;
var children = new RegExp(brackets);
var match = prefix.exec(string);
if (match[1]) {
keys.push(match[1]);
}
while ((match = children.exec(string)) !== null) {
keys.push(match[1]);
}
return keys;
}
function hash_assign(result, keys, value) {
if (keys.length === 0) {
result = value;
return result;
}
var key = keys.shift();
var between = key.match(/^\[(.+?)\]$/);
if (key === '[]') {
result = result || [];
if (Array.isArray(result)) {
result.push(hash_assign(null, keys, value));
}
else {
// This might be the result of bad name attributes like "[][foo]",
// in this case the originalresult
object will already be
// assigned to an object literal. Rather than coerce the object to
// an array, or cause an exception the attribute "_values" is
// assigned as an array.
result._values = result._values || [];
result._values.push(hash_assign(null, keys, value));
}
return result;
}
// Key is an attribute name and can be assigned directly.
if (!between) {
result[key] = hash_assign(result[key], keys, value);
}
else {
var string = between[1];
// +var converts the variable into a number
// better than parseInt because it doesn't truncate away trailing
// letters and actually fails if whole thing is not a number
var index = +string;
// If the characters between the brackets is not a number it is an
// attribute name and can be assigned directly.
if (isNaN(index)) {
result = result || {};
result[string] = hash_assign(result[string], keys, value);
}
else {
result = result || [];
result[index] = hash_assign(result[index], keys, value);
}
}
return result;
}
// Object/hash encoding serializer.
function hash_serializer(result, key, value) {
var matches = key.match(brackets);
// Has brackets? Use the recursive assignment function to walk the keys,
// construct any missing objects in the result tree and make the assignment
// at the end of the chain.
if (matches) {
var keys = parse_keys(key);
hash_assign(result, keys, value);
}
else {
// Non bracket notation can make assignments directly.
var existing = result[key];
// If the value has been assigned already (for instance when a radio and
// a checkbox have the same name attribute) convert the previous value
// into an array before pushing into it.
//
// NOTE: If this requirement were removed all hash creation and
// assignment could go throughhash_assign
.
if (existing) {
if (!Array.isArray(existing)) {
result[key] = [ existing ];
}
result[key].push(value);
}
else {
result[key] = value;
}
}
return result;
}
// urlform encoding serializer
function str_serialize(result, key, value) {
// encode newlines as \r\n cause the html spec says so
value = value.replace(/(\r)?\n/g, '\r\n');
value = encodeURIComponent(value);
// spaces should be '+' rather than '%20'.
value = value.replace(/%20/g, '+');
return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + value;
}
//module.exports = serialize;
使用
引入
调用
coanst data=serialize(表单对象,{hash:true,empty:true})
返回:对象
{表单项name:value}
参数
参数1:表单对象
参数2:配置对象
hash:设置获取数据结构
true//JS对象(推荐)
false//查询字符串
empty:是否获取空值
AJAX简介
定义:浏览器与服务器进行数据通信的技术
AJAX作用
发起HTTP请求
GET 请求:用于从服务器请求数据。
POST 请求:用于向服务器发送数据,通常用于创建资源。
PUT 请求:用于更新服务器上的资源。
DELETE 请求:用于从服务器删除资源。
AJAX原理
XMLHttpRequest
语法
//创建XMLHttpRequest对象 const xhr = new XMLHttpRequest() //调用open方法,配置请求方法和url xhr.open('请求方法',url) //监听loadend事件,接受响应结果 xhr.addEventListener('loadend', () => { console.log(xhr.response) xhr.status//本次请求的状态码 }) //发起请求 chr.send()
查询参数
修改url
url后面+
?参数名1=值&参数名2=值
组织查询参数字符串
const Obj={
参数1:值,
参数2:值
}//查询参数对象
const paramsObj=new URLSearchParams(Obj)
//url使用模板字符串添加${paramsObj.toString()}
数据提交
语法
const xhr = new XMLHttpRequest()
xhr.open('请求方法',url)
xhr.addEventListener('loadend', () => {
console.log(xhr.response)
})
//请求头:设置content-Type:application/json
xhr.setRequestHeader('content-Type','application/json')
//请求体:携带JSON字符串
const Obj{}//***数据填写位置
const ObjStr=JSON.stringfy(ObjStr)
//发送集体请求
chr.send(ObjStr)
Promise对象
作用
表示一个异步操作的完成(或失败)及其结果
状态
pending(进行中)
fulfilled(已成功)
rejected(已失败)
语法
//1.创建Promise对象
const Obj=new Promise((resolve,reject)=>{
//2.执行异步任务,并传递结果
setTimeout(()=>{
resolve('传递成功结果')//二选一
reject(new Error('传递失败结果'))//二选一
},2000)
})
//参数1:resolve函数:设置promise状态为成功,触发then()执行
//参数2:reject函数:promise状态为失败,触发catch()执行
//3.接收结果
Obj.then(result=>{
//成功
}).catch(error=>{
//失败
console.dir(error)//错误对象详细打印
})
链式调用
步骤
在本次then函数中返回一个新的promise对象
新对象将在逻辑上以本次成功状态为前置条件
async,await
定义:简便使用promise链式调用
语法:
async function xxx(){}
添加async关键字的函数将成为异步函数
await promise对象
暂停函数代码执行
直至promise对象完成,并获取其成功结果
错误捕获
try{
执行代码}catch(error){
//执行代码错误进入此处
console.dir(error)//错误的详细信息
}说明
try里面的某行代码报错后,剩余代码不执行
all静态方法
概念
合并多个promise对象
等待所有promise对象全部成功(或一个失败)
做后续逻辑
语法
const p=Promise.all([promise对象,promise对象])
p.then(result=>{
//结果数组的顺序与合并时的顺序一致
}).catch(error=.{})
回调函数地狱
概念
多个回调函数嵌套
缺点
可读性差
异常无法捕获
耦合性严重
解决方案
promise链式调用
请求拦截器
说明
发起请求之前,触发配置函数
对请求参数进行额外配置
语法
//添加请求拦截器
axios.interceptors.request.use(function (config) {
//在发送请求之前做什么
return config
}, function (error) {
//请求错误做什么
return Promise.reject(error)
})
eg
axios.interceptors.request.use(function (config) {
//获取token字符串
const token = localStorage.getItem('token')
//设置请求头
token && ( config.headers.Authorization=`Bearer ${token}`)
return config
}, function (error) {
return Promise.reject(error)
})
响应拦截器
说明
响应回到then/catch之前,触发拦截器函数
对响应结果统一处理
语法
//添加响应拦截器
axios.interceptors.response.use(function (response) {
//在发送请求之前做什么
return response
}, function (error) {
//请求错误做什么
return Promise.reject(error)
})
eg
////添加响应拦截器
axios.interceptors.response.use(function (response) {
return response
}, function (error) {
//如果响应状态为401
//清空本地存储
//返回登录页面
if (error?.response?.status === 401) {
alert('登录状态已过期')
localStorage.clear()
location.href = '../login/index.html'
}
return Promise.reject(error)
})