共计 11146 个字符,预计需要花费 28 分钟才能阅读完成。
接口调用形式
- 原生 ajax
- 基于 jQuery 的 ajax
- fetch
- axios
异步
- JavaScript 的执行环境是「单线程」
- 所谓单线程,是指 JS 引擎中负责解释和执行 JavaScript 代码的线程只有一个,也就是一次只能实现一项工作,这个工作执行完后能力执行下一个,它会「阻塞」其余工作。这个工作可称为主线程
- 异步模式能够一起执行 多个工作
-
JS 中常见的异步调用
- 定时任何
- ajax
- 事件函数
promise
- 次要解决异步深层嵌套的问题
- promise 提供了简洁的 API 使得异步操作更加容易
<script type="text/javascript">
/*
1. Promise 根本应用
咱们应用 new 来构建一个 Promise Promise 的构造函数接管一个参数,是函数,并且传入两个参数:resolve,reject,别离示意异步操作执行胜利后的回调函数和异步操作执行失败后的回调函数
*/
var p = new Promise(function(resolve, reject){
//2. 这里用于实现异步工作 setTimeout
setTimeout(function(){
var flag = false;
if(flag) {
//3. 失常状况
resolve('hello');
}else{
//4. 异常情况
reject('出错了');
}
}, 100);
});
// 5 Promise 实例生成当前,能够用 then 办法指定 resolved 状态和 reject 状态的回调函数
// 在 then 办法中,你也能够间接 return 数据而不是 Promise 对象,在前面的 then 中就能够接管到数据了
p.then(function(data){console.log(data)
},function(info){console.log(info)
});
</script>
基于 Promise 发送 Ajax 申请
<script type="text/javascript">
/*
基于 Promise 发送 Ajax 申请
*/
function queryData(url) {
# 1.1 创立一个 Promise 实例
var p = new Promise(function(resolve, reject){var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){if(xhr.readyState != 4) return;
if(xhr.readyState == 4 && xhr.status == 200) {
# 1.2 解决失常的状况
resolve(xhr.responseText);
}else{
# 1.3 解决异常情况
reject('服务器谬误');
}
};
xhr.open('get', url);
xhr.send(null);
});
return p;
}
# 留神:这里须要开启一个服务
# 在 then 办法中,你也能够间接 return 数据而不是 Promise 对象,在前面的 then 中就能够接管到数据了,这时的 then 会产生一个默认的 Promise 实例对象来调用这个 then
queryData('http://localhost:3000/data')
.then(function(data){console.log(data)
# 1.4 想要持续链式编程上来 须要 return
return queryData('http://localhost:3000/data1');
})
.then(function(data){console.log(data);
return queryData('http://localhost:3000/data2');
})
.then(function(data){console.log(data)
});
</script>
Promise 根本 API
实例办法
.then()
- 失去异步工作正确的后果
.catch()
- 获取异样信息
.finally()
- 胜利与否都会执行(不是正式规范)
<script type="text/javascript">
/*
Promise 罕用 API- 实例办法
*/
// console.dir(Promise);
function foo() {return new Promise(function(resolve, reject){setTimeout(function(){// resolve(123);
reject('error');
}, 100);
})
}
// foo()
// .then(function(data){// console.log(data)
// })
// .catch(function(data){// console.log(data)
// })
// .finally(function(){// console.log('finished')
// });
// --------------------------
// 两种写法是等效的
foo()
.then(function(data){
# 失去异步工作正确的后果
console.log(data)
},function(data){
# 获取异样信息
console.log(data)
})
# 胜利与否都会执行(不是正式规范).finally(function(){console.log('finished')
});
</script>
对象办法
.all()
Promise.all
办法承受一个数组作参数,数组中的对象(p1、p2、p3)均为 promise 实例(如果不是一个 promise,该项会被用Promise.resolve
转换为一个 promise)。它的状态由这三个 promise 实例决定
.race()
Promise.race
办法同样承受一个数组作参数。当 p1, p2, p3 中有一个实例的状态产生扭转(变为fulfilled
或rejected
),p 的状态就跟着扭转。并把第一个扭转状态的 promise 的返回值,传给 p 的回调函数
<script type="text/javascript">
/*
Promise 罕用 API- 对象办法
*/
// console.dir(Promise)
function queryData(url) {return new Promise(function(resolve, reject){var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){if(xhr.readyState != 4) return;
if(xhr.readyState == 4 && xhr.status == 200) {
// 解决失常的状况
resolve(xhr.responseText);
}else{
// 解决异常情况
reject('服务器谬误');
}
};
xhr.open('get', url);
xhr.send(null);
});
}
var p1 = queryData('http://localhost:3000/a1');
var p2 = queryData('http://localhost:3000/a2');
var p3 = queryData('http://localhost:3000/a3');
Promise.all([p1,p2,p3]).then(function(result){// all 中的参数 [p1,p2,p3] 和 返回的后果一 一对应["HELLO TOM", "HELLO JERRY", "HELLO SPIKE"]
console.log(result) //["HELLO TOM", "HELLO JERRY", "HELLO SPIKE"]
})
Promise.race([p1,p2,p3]).then(function(result){// 因为 p1 执行较快,Promise 的 then()将取得后果 'P1'。p2,p3 仍在继续执行,但执行后果将被抛弃。console.log(result) // "HELLO TOM"
})
</script>
fetch
- Fetch API 是新的 ajax 解决方案 Fetch 会返回 Promise
- fetch 不是 ajax 的进一步封装,而是原生 js,没有应用 XMLHttpRequest 对象。
- fetch(url, options).then()
<script type="text/javascript">
/*
Fetch API 根本用法
fetch(url).then()
第一个参数申请的门路 Fetch 会返回 Promise 所以咱们能够应用 then 拿到申请胜利的后果
*/
fetch('http://localhost:3000/fdata').then(function(data){// text()办法属于 fetchAPI 的一部分,它返回一个 Promise 实例对象,用于获取后盾返回的数据
return data.text();}).then(function(data){
// 在这个 then 外面咱们能拿到最终的数据
console.log(data);
})
</script>
fetch API 中的 HTTP 申请
- fetch(url, options).then()
-
HTTP 协定,它给咱们提供了很多的办法,如 POST,GET,DELETE,UPDATE,PATCH 和 PUT
- 默认的是 GET 申请
- 须要在 options 对象中 指定对应的 method method: 申请应用的办法
- post 和 一般 申请的时候 须要在 options 中 设置 申请头 headers 和 body
<script type="text/javascript">
/*
Fetch API 调用接口传递参数
*/
#1.1 GET 参数传递 - 传统 URL 通过 url?的模式传参
fetch('http://localhost:3000/books?id=123', {
# get 申请能够省略不写 默认的是 GET
method: 'get'
})
.then(function(data) {
# 它返回一个 Promise 实例对象,用于获取后盾返回的数据
return data.text();}).then(function(data) {
# 在这个 then 外面咱们能拿到最终的数据
console.log(data)
});
#1.2 GET 参数传递 restful 模式的 URL 通过 / 的模式传递参数 即 id = 456 和 id 后盾的配置无关
fetch('http://localhost:3000/books/456', {
# get 申请能够省略不写 默认的是 GET
method: 'get'
})
.then(function(data) {return data.text();
}).then(function(data) {console.log(data)
});
#2.1 DELETE 申请形式参数传递 删除 id 是 id=789
fetch('http://localhost:3000/books/789', {method: 'delete'})
.then(function(data) {return data.text();
}).then(function(data) {console.log(data)
});
#3 POST 申请传参
fetch('http://localhost:3000/books', {
method: 'post',
# 3.1 传递数据
body: 'uname=lisi&pwd=123',
# 3.2 设置申请头
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
.then(function(data) {return data.text();
}).then(function(data) {console.log(data)
});
# POST 申请传参
fetch('http://localhost:3000/books', {
method: 'post',
body: JSON.stringify({
uname: '张三',
pwd: '456'
}),
headers: {'Content-Type': 'application/json'}
})
.then(function(data) {return data.text();
}).then(function(data) {console.log(data)
});
# PUT 申请传参 批改 id 是 123 的
fetch('http://localhost:3000/books/123', {
method: 'put',
body: JSON.stringify({
uname: '张三',
pwd: '789'
}),
headers: {'Content-Type': 'application/json'}
})
.then(function(data) {return data.text();
}).then(function(data) {console.log(data)
});
</script>
fetchAPI 中 响应格局
- 用 fetch 来获取数据,如果响应失常返回,咱们首先看到的是一个 response 对象,其中包含返回的一堆原始字节,这些字节须要在收到后,须要咱们通过调用办法将其转换为相应格局的数据,比方
JSON
,BLOB
或者TEXT
等等
/*
Fetch 响应后果的数据格式
*/
fetch('http://localhost:3000/json').then(function(data){// return data.json(); // 将获取到的数据应用 json 转换对象
return data.text(); // // 将获取到的数据 转换成字符串}).then(function(data){// console.log(data.uname)
// console.log(typeof data)
var obj = JSON.parse(data);
console.log(obj.uname,obj.age,obj.gender)
})
axios
- 基于 promise 用于浏览器和 node.js 的 http 客户端
- 反对浏览器和 node.js
- 反对 promise
- 能拦挡申请和响应
- 主动转换 JSON 数据
- 能转换申请和响应数据
axios 根底用法
-
get 和 delete 申请传递参数
- 通过传统的 url 以 ? 的模式传递参数
- restful 模式传递参数
- 通过 params 模式传递参数
-
post 和 put 申请传递参数
- 通过选项传递参数
- 通过 URLSearchParams 传递参数
# 1. 发送 get 申请
axios.get('http://localhost:3000/adata').then(function(ret){
# 拿到 ret 是一个对象 所有的对象都存在 ret 的 data 属性外面
// 留神 data 属性是固定的用法,用于获取后盾的理论数据
// console.log(ret.data)
console.log(ret)
})
# 2. get 申请传递参数
# 2.1 通过传统的 url 以 ? 的模式传递参数
axios.get('http://localhost:3000/axios?id=123').then(function(ret){console.log(ret.data)
})
# 2.2 restful 模式传递参数
axios.get('http://localhost:3000/axios/123').then(function(ret){console.log(ret.data)
})
# 2.3 通过 params 模式传递参数
axios.get('http://localhost:3000/axios', {
params: {id: 789}
}).then(function(ret){console.log(ret.data)
})
#3 axios delete 申请传参 传参的模式和 get 申请一样
axios.delete('http://localhost:3000/axios', {
params: {id: 111}
}).then(function(ret){console.log(ret.data)
})
# 4 axios 的 post 申请
# 4.1 通过选项传递参数
axios.post('http://localhost:3000/axios', {
uname: 'lisi',
pwd: 123
}).then(function(ret){console.log(ret.data)
})
# 4.2 通过 URLSearchParams 传递参数(application/x-www-form-urlencoded)var params = new URLSearchParams();
params.append('uname', 'zhangsan');
params.append('pwd', '111');
axios.post('http://localhost:3000/axios', params).then(function(ret){console.log(ret.data)
})
#5 axios put 申请传参 和 post 申请一样
axios.put('http://localhost:3000/axios/123', {
uname: 'lisi',
pwd: 123
}).then(function(ret){console.log(ret.data)
})
axios 全局配置
# 配置公共的申请头
axios.defaults.baseURL = 'https://api.example.com';
# 配置 超时工夫
axios.defaults.timeout = 2500;
# 配置申请头信息
axios.defaults.headers['mytoken'] = '自定义';
# 配置公共的申请头
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
# 配置公共的 post 的 Content-Type
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
axios 拦截器
-
申请拦截器
-
申请拦截器的作用是在申请发送前进行一些操作
- 例如在每个申请体里加上 token,对立做了解决如果当前要改也非常容易
-
-
响应拦截器
-
响应拦截器的作用是在接管到响应后进行一些操作
- 例如在服务器返回登录状态生效,须要从新登录的时候,跳转到登录页
-
# 1. 申请拦截器
axios.interceptors.request.use(function(config) {console.log(config.url)
# 1.1 任何申请都会通过这一步 在发送申请之前做些什么
config.headers.mytoken = 'nihao';
# 1.2 这里肯定要 return 否则配置不胜利
return config;
}, function(err){
#1.3 对申请谬误做点什么
console.log(err)
})
#2. 响应拦截器
axios.interceptors.response.use(function(res) {
#2.1 在接管响应做些什么
var data = res.data;
return data;
}, function(err){
#2.2 对响应谬误做点什么
console.log(err)
})
async 和 await
-
async 作为一个关键字放到函数后面
- 任何一个
async
函数都会隐式返回一个promise
- 任何一个
-
await
关键字只能在应用async
定义的函数中应用- await 前面能够间接跟一个 Promise 实例对象
- await 函数不能独自应用
- async/await 让异步代码看起来、体现起来更像同步代码
# 1. async 根底用法
# 1.1 async 作为一个关键字放到函数后面
async function queryData() {
# 1.2 await 关键字只能在应用 async 定义的函数中应用 await 前面能够间接跟一个 Promise 实例对象
var ret = await new Promise(function(resolve, reject){setTimeout(function(){resolve('nihao')
},1000);
})
// console.log(ret.data)
return ret;
}
# 1.3 任何一个 async 函数都会隐式返回一个 promise 咱们能够应用 then 进行链式编程
queryData().then(function(data){console.log(data)
})
#2. async 函数解决多个异步函数
axios.defaults.baseURL = 'http://localhost:3000';
async function queryData() {
# 2.1 增加 await 之后 以后的 await 返回后果之后才会执行前面的代码
var info = await axios.get('async1');
#2.2 让异步代码看起来、体现起来更像同步代码
var ret = await axios.get('async2?info=' + info.data);
return ret.data;
}
queryData().then(function(data){console.log(data)
})
图书列表案例
1. 基于接口案例 - 获取图书列表
- 导入 axios 用来发送 ajax
- 把获取到的数据渲染到页面上
<div id="app">
<div class="grid">
<table>
<thead>
<tr>
<th> 编号 </th>
<th> 名称 </th>
<th> 工夫 </th>
<th> 操作 </th>
</tr>
</thead>
<tbody>
<!-- 5. 把 books 中的数据渲染到页面上 -->
<tr :key='item.id' v-for='item in books'>
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.date}}</td>
<td>
<a href=""> 批改 </a>
<span>|</span>
<a href=""> 删除 </a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
1. 导入 axios
<script type="text/javascript" src="js/axios.js"></script>
<script type="text/javascript">
/*
图书治理 - 增加图书
*/
# 2 配置公共的 url 地址 简化前面的调用形式
axios.defaults.baseURL = 'http://localhost:3000/';
axios.interceptors.response.use(function(res) {return res.data;}, function(error) {console.log(error)
});
var vm = new Vue({
el: '#app',
data: {
flag: false,
submitFlag: false,
id: '',
name: '',
books: []},
methods: {
# 3 定义一个办法 用来发送 ajax
# 3.1 应用 async 来 让异步的代码 以同步的模式书写
queryData: async function() {
// 调用后盾接口获取图书列表数据
// var ret = await axios.get('books');
// this.books = ret.data;
# 3.2 发送 ajax 申请 把拿到的数据放在 books 外面
this.books = await axios.get('books');
}
},
mounted: function() {
# 4 mounted 外面 DOM 曾经加载结束 在这里调用函数
this.queryData();}
});
</script>
2 增加图书
- 获取用户输出的数据 发送到后盾
- 渲染最新的数据到页面上
methods: {handle: async function(){if(this.flag) {
// 编辑图书
// 就是依据以后的 ID 去更新数组中对应的数据
this.books.some((item) => {if(item.id == this.id) {
item.name = this.name;
// 实现更新操作之后,须要终止循环
return true;
}
});
this.flag = false;
}else{
# 1.1 在后面封装好的 handle 办法中 发送 ajax 申请
# 1.2 应用 async 和 await 简化操作 须要在 function 后面增加 async
var ret = await axios.post('books', {name: this.name})
# 1.3 依据后盾返回的状态码判断是否加载数据
if(ret.status == 200) {
# 1.4 调用 queryData 这个办法 渲染最新的数据
this.queryData();}
}
// 清空表单
this.id = '';
this.name = '';
},
}
3 验证图书名称是否存在
- 增加图书之前发送申请验证图示是否曾经存在
-
如果不存在 往后台外面增加图书名称
- 图书存在与否只须要批改 submitFlag 的值即可
watch: {name: async function(val) {
// 验证图书名称是否曾经存在
// var flag = this.books.some(function(item){
// return item.name == val;
// });
var ret = await axios.get('/books/book/' + this.name);
if(ret.status == 1) {
// 图书名称存在
this.submitFlag = true;
}else{
// 图书名称不存在
this.submitFlag = false;
}
}
},
4. 编辑图书
- 依据以后书的 id 查问须要编辑的书籍
- 须要依据状态位判断是增加还是编辑
methods: {handle: async function(){if(this.flag) {
#4.3 编辑图书 把用户输出的信息提交到后盾
var ret = await axios.put('books/' + this.id, {name: this.name});
if(ret.status == 200){
#4.4 实现增加后 从新加载列表数据
this.queryData();}
this.flag = false;
}else{
// 增加图书
var ret = await axios.post('books', {name: this.name})
if(ret.status == 200) {
// 从新加载列表数据
this.queryData();}
}
// 清空表单
this.id = '';
this.name = '';
},
toEdit: async function(id){
#4.1 flag 状态位用于辨别编辑和增加操作
this.flag = true;
#4.2 依据 id 查问出对应的图书信息 页面中能够加载进去最新的信息
# 调用接口发送 ajax 申请
var ret = await axios.get('books/' + id);
this.id = ret.id;
this.name = ret.name;
},
5 删除图书
- 把须要删除的 id 书籍 通过参数的模式传递到后盾
deleteBook: async function(id){
// 删除图书
var ret = await axios.delete('books/' + id);
if(ret.status == 200) {
// 从新加载列表数据
this.queryData();}
}
正文完