1 基础概念

1.1 接口调用的方式

  • 原生 ajax 
  • 基于 jQuery 的ajax 
  • fetch 
  • axios

1.2 URL格式

格式:schema://host:port/path?query#fragment
① schema:协议。例如http、https、ftp等
② host:域名或者IP地址
③ port:端口, http默认端口80,可以省略
④ path:路径, 例如/abc/a/b/c
⑤ query :查询参数,例如 uname=lisi&age=12
⑥ fragment :锚点(哈希Hash),用于定位页面的某个位置

Restful: http://www.hello.com/books/123

1.3 http请求方式

① GET 查询
② POST 添加
③ PUT 修改
④ DELETE 删除 

2 异步解决方案 Promise

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
异步:
① 定时任务
② Ajax
③ 事件函数

2.1 传统多次异步调用依赖产生问题—回调地狱

异步调用结果如果存在依赖需要嵌套,依赖就是需要顺序输出。

  1. $.ajax({
  2. success: function (data) {
  3. if (data.status == 200) {
  4. $.ajax({
  5. success: function (data) {
  6. if (data.status == 200) {
  7. $.ajax({
  8. success: function (data) {
  9. if (data.status == 200) { }
  10. }
  11. });
  12. }
  13. }
  14. });
  15. }
  16. }
  17. });

2.2 Promise基本用法

Promise 是异步编程的一种解决方案。
类型是函数。也是一个对象,可以获取异步操作的消息。
它提供了简洁的API,使得控制异步操作更加容易。

  • resolve 和 reject 两个参数用于处理成功和失败两种情况,
  • 当异步任务顺利完成且返回结果值时,会调用 resolve 函数;而当异步任务失败且返回失败原因(通常是一个错误对象)时,会调用reject 函数,并通过 p.then 获取处理结果
    1. var p = new Promise(function(resolve, reject){
    2. // 成功时调用 resolve()
    3. // 失败时调用 reject()
    4. });
    5. p.then(function(ret){
    6. // 从resolve得到正常结果
    7. }, function(ret){
    8. // 从reject得到错误信息
    9. });
    案例: ```javascript var p = new Promise(function (resolve, reject) { setTimeout(function () { var flag = true; flag ? resolve(‘nice’) : reject(‘err,hehehe’) }) });

p.then(ok => { console.log(ok) }, err => { console.log(err) })

  1. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1688721/1625290651720-046d07cf-1bc0-42b2-89bd-f5ce13699002.png#height=51&id=bIs04&margin=%5Bobject%20Object%5D&name=image.png&originHeight=102&originWidth=708&originalType=binary&ratio=1&size=3076&status=done&style=none&width=354)
  2. <a name="vHRDd"></a>
  3. ## 2.3 封装ajax,发送多个请求
  4. 单次调用
  5. ```javascript
  6. function queryDate(url) {
  7. var p = new Promise(function (resolve, reject) {
  8. var xhr = new XMLHttpRequest();
  9. xhr.onreadystatechange = function () {
  10. if (xhr.readyState != 4) return;
  11. if (xhr.readyState == 4 && xhr.status == 200) {
  12. resolve(xhr.responseText);
  13. } else {
  14. reject('服务器异常');
  15. }
  16. }
  17. xhr.open('get', url);
  18. xhr.send(null);
  19. })
  20. return p
  21. }
  22. queryDate('http://localhost:3000/data')
  23. .then(function (data) {
  24. console.log(data);
  25. }, function (info) {
  26. console.log(info);
  27. })

多次调用:

  1. queryDate('http://localhost:3000/data')
  2. .then(function (data) {
  3. console.log(data);
  4. return queryDate('http://localhost:3000/data1');
  5. }).then(function (data) {
  6. console.log(data);
  7. return queryDate('http://localhost:3000/data2');
  8. }).then(function (data) {
  9. console.log(data);
  10. })

image.png
通过返回Promise实例对象,调用下一个then,变成链式从而解决回调地狱。

2.4 then参数的函数返回值

若是返回一个普通值,这个也会产生一个默认的Promise对象继续可以使用then,通过 then 参数中函数的参数接收该值。

  1. queryDate('http://localhost:3000/data')
  2. .then(function (data) {
  3. console.log(data);
  4. return "helloworld";
  5. }).then(data => {
  6. console.log(data);
  7. })

image.png

2.5 Promise实例方法

  • p.then() 得到异步任务的正确结果 
  • p.catch() 获取异常信息 
  • p.finally() 成功与否都会执行(尚且不是正式标准)
  1. function foo() {
  2. return new Promise(function(resolve, reject) {
  3. setTimeout(function(){
  4. reject('err')
  5. }, 100);
  6. });
  7. }
  8. foo().then(data => {
  9. console.log(data);
  10. }).catch( err=>{
  11. console.log(err);
  12. }).finally(function() {
  13. console.log('finish end');
  14. })

image.png

  1. foo().then(data => {
  2. console.log(data);
  3. }).catch( err=>{
  4. console.log(err);
  5. })
  6. 等价于
  7. foo().then(data => {
  8. console.log(data);
  9. },err=>{
  10. console.log(err);
  11. })

2.6 Promise对象方法

  • Promise.all() 并发处理多个异步任务,所有任务都执行完成才能得到结果 
  • Promise.race() 并发处理多个异步任务,只要有一个任务完成就能得到结果 ```javascript function queryDate(url) { var p = new Promise(function (resolve, reject) { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () {
    1. if (xhr.readyState != 4) return;
    2. if (xhr.readyState == 4 && xhr.status == 200) {
    3. resolve(xhr.responseText);
    4. } else {
    5. reject('服务器异常');
    6. }
    } xhr.open(‘get’, url); xhr.send(null); }) return p; }

var p1 = queryDate(‘http://localhost:3000/a1‘); var p2 = queryDate(‘http://localhost:3000/a2‘); var p3 = queryDate(‘http://localhost:3000/a3‘); Promise.all([p1, p2, p3]).then(result => { console.log(result); }); Promise.race([p1, p2, p3]).then(result => { console.log(result); });

  1. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1688721/1625297953566-af6a57d8-a8f1-4a57-8192-2b613e0ad412.png#height=75&id=AMrOv&margin=%5Bobject%20Object%5D&name=image.png&originHeight=150&originWidth=954&originalType=binary&ratio=1&size=14623&status=done&style=none&width=477)
  2. <a name="XrNQl"></a>
  3. # 3 fetch
  4. [https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)<br />更加简单的数据获取方式,功能更强大、更灵活,可以看做是xhr的升级版<br />基于Promise实现
  5. <a name="YpY5d"></a>
  6. ## 3.1 基本使用
  7. 常用配置选项
  8. - method(String): HTTP请求方法,默认为GET (GETPOSTPUTDELETE)
  9. - body(String): HTTP的请求参数
  10. - headers(Object): HTTP的请求头,默认为{}
  11. 默认请求方式是get
  12. ```javascript
  13. fetch('http://localhost:3000/fdata').then(function(data){
  14. console.log(data);
  15. // text()方法属于fetchAPI一部分,返回一个Promise实例对象,用于获取后台返回数据
  16. return data.text();
  17. }).then(function(data){
  18. // 注意这里得到的才是最终的数据
  19. console.log(data);
  20. });

image.png

3.2 delete请求方式

  1. fetch('/abc/123', {
  2. method: 'delete'
  3. }).then(data => {
  4. return data.text();
  5. }).then(ret => {
  6. // 注意这里得到的才是最终的数据
  7. console.log(ret);
  8. });

3.3 post请求方式

  1. fetch('http://localhost:3000/books', {
  2. method: 'post',
  3. body: 'uname=lisi&pwd=123',
  4. headers: {
  5. 'Content-Type': 'application/x-www-form-urlencoded',
  6. }
  7. }).then(data => {
  8. return data.text();
  9. }).then(ret => {
  10. console.log(ret);
  11. });

3.4 put请求方式

  1. fetch('http://localhost:3000/books/123', {
  2. method: 'PUT',
  3. body: JSON.stringify({
  4. uname: '张三',
  5. pwd: '789'
  6. }),
  7. headers: {
  8. 'Content-Type': 'application/json'
  9. }
  10. })
  11. .then(function(data){
  12. return data.text();
  13. }).then(function(data){
  14. console.log(data)
  15. });

3.5 返回JSON格式数据

响应数据格式 

  • text(): 将返回体处理成字符串类型 
  • json():返回结果和 JSON.parse(responseText)一样
    1. fetch('/abc' then(data=>{
    2. // return data.text();
    3. return data.json();
    4. }).then(ret=>{
    5. console.log(ret);
    6. });

4 axios

它的底层也是封装xhr
axios(官网:https://github.com/axios/axios
是一个基于Promise 用于浏览器和 node.js 的 HTTP 客户端。

  • 支持浏览器和 node.js 
  • 支持 promise 
  • 能拦截请求和响应 
  • 自动转换 JSON 数据

    4.1 基本用法

    data属性名称是固定的,用于获取后台响应的数据
    1. axios.get('http://localhost:3000/adata').then(el => {
    2. console.log(el.data);
    3. })
    image.png

    4.2 get带参数请求

    ```javascript axios.get(‘/adata?id=123’).then(ret=>{
    1. console.log(ret.data)
    })

axios.get(‘/adata/123’).then(ret=>{ console.log(ret.data) })

axios.get(‘/adata’,{ params: { id: 123 } }).then(ret=>{ console.log(ret.data) })

  1. <a name="03KfE"></a>
  2. ## 4.3 delete
  3. ```javascript
  4. axios.delete('/adata?id=123').then(ret=>{
  5. console.log(ret.data)
  6. });
  7. axios.delete('/adata/123').then(ret=>{
  8. console.log(ret.data)
  9. });
  10. axios.delete(‘/adata‘,{params: {id: 123}}).then(ret=>{
  11. console.log(ret.data)
  12. })

4.4 post

默认传递的是 json 格式的数据

  1. axios.post('/adata',{
  2. uname: 'tom',
  3. pwd: 123
  4. }).then(ret=>{
  5. console.log(ret.data)
  6. })

通过 URLSearchParams 传递参数(application/x-www-form-urlencoded)
**URLSearchParams** 接口定义了一些实用的方法来处理 URL 的查询字符串
[URLSearchParams.append()](https://developer.mozilla.org/zh-CN/docs/Web/API/URLSearchParams/append)插入一个指定的键/值对作为新的搜索参数。

  1. const params = new URLSearchParams();
  2. params.append('param1', 'value1');
  3. params.append('param2', 'value2');
  4. axios.post('/api/test', params).then(ret=>{
  5. console.log(ret.data)
  6. })

4.5 put

  1. axios.put(‘/adata/123',{
  2. uname: 'tom',
  3. pwd: 123
  4. }).then(ret=>{
  5. console.log(ret.data)
  6. })

4.6 axios 的响应结果

响应结果的主要属性 

  • data : 实际响应回来的数据 
  • headers :响应头信息 
  • status :响应状态码 
  • statusText :响应状态信息
    1. axios.post('/axios-json').then(ret=>{
    2. console.log(ret)
    3. })
    image.png

4.7 全局配置

  1. axios.defaults.timeout = 3000; // 超时时间
  2. axios.defaults.baseURL = 'http://localhost:3000/app'; // 默认地址
  3. axios.defaults.headers['mytoken'] = 'aqwerwqwerqwer2ewrwe23eresdf23’// 设置请求头

4.8 axios拦截器请求拦截器

image.png

  1. //添加一个请求拦截器
  2. axios.interceptors.request.use(function(config){
  3. //在请求发出之前进行一些信息设置
  4. return config;
  5. },function(err){
  6. // 处理响应的错误信息
  7. });

4.9 响应拦截器

image.png

  1. //添加一个响应拦截器
  2. axios.interceptors.response.use(function(res){
  3. //在这里对返回的数据进行处理
  4. return res;
  5. },function(err){
  6. // 处理响应的错误信息
  7. })

案例:

  1. axios.interceptors.request.use(function(config) {
  2. console.log(config.url)
  3. config.headers.mytoken = 'nihao';
  4. return config;
  5. }, function(err){
  6. console.log(err)
  7. })
  8. axios.interceptors.response.use(function(res) {
  9. var data = res.data;
  10. return data;
  11. }, function(err){
  12. console.log(err)
  13. })
  14. axios.get('http://localhost:3000/adata').then(function(data){
  15. console.log(data)
  16. })

image.png
image.png

5 async/await

  • async/await是ES7引入的新语法,可以更加方便的进行异步操作 
  • async 关键字用于函数上(async函数的返回值是Promise实例对象) 
  • await 关键字用于 async 函数当中(await可以得到异步的结果)

    5.1 基本使用

    1. async function queryData(id) {
    2. const ret = await axios.get('/data');
    3. return ret;
    4. }
    5. queryData.then(ret=>{
    6. console.log(ret)
    7. })

    使用案例:

    1. deleteBook: async function (i) {
    2. var val = await axios.delete('books/' + i);
    3. val.status == 200 && this.queryDate();
    4. },
  • 因为async函数的返回值是Promise实例对象

  • await 右侧的表达式一般为 promise 对象
  • await 返回的是 promise 成功的值
  • await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理

5.2 多个异步请求

  1. async function queryData(id) {
  2. const info = await axios.get('/async1');
  3. const ret = await axios.get(‘async2?info=‘+info.data);
  4. return ret;
  5. }
  6. queryData.then(ret=>{
  7. console.log(ret)
  8. })

5.3 使用then和不使用then

两个console.log()值都一样

  1. async function getList() {
  2. var url = 'http://www.liulongbin.top:3006/api/get'
  3. // 请求的参数对象
  4. var paramsObj = { name: 'zs', age: 20 }
  5. const result = await axios.get(url, { params: paramsObj })
  6. console.log(result);
  7. return result
  8. }
  9. getList().then(ret => {
  10. console.log(ret)
  11. })

image.png