axios

文章基于尚硅谷

HTTP

1. 前后台交互的基本过程

在这里插入图片描述

 

1. 前后应用从浏览器端向服务器发送HTTP请求(请求报文)
2. 后台服务器接收到请求后, 调度服务器应用处理请求, 向浏览器端返回HTTP响应(响应报文)
3. 浏览器端接收到响应, 解析显示响应体/调用监视回调

HTTP请求报文

请求行:

请求方式/url
常用请求方式get post delete put  

POST /login

多个请求头

Host: www.baidu.com
Cookie: BAIDUID=AD3B0FA706E; BIDUPSID=AD3B0FA706;
Content-Type: application/x-www-form-urlencoded 或者application/json

请求体

username=tom&pwd=123   urlencoded
{"username": "tom", "pwd": 123}   json

HTTP 响应报文

响应状态行:

status

statusText

多个响应头

Content-Type: text/html;charset=utf-8
Set-Cookie: BD_CK_SAM=1;path=/

响应体

html 文本/json 文本/js/css/图片...

post 请求体参数格式

1.Content-Type: application/x-www-form-urlencoded;charset=utf-8
用于键值对参数,参数的键值用=连接, 参数之间用&连接
例如: name=%E5%B0%8F%E6%98%8E&age=12
2.Content-Type: application/json;charset=utf-8
用于 json 字符串参数
例如: {"name": "%E5%B0%8F%E6%98%8E", "age": 12}
3.Content-Type: multipart/form-data
用于文件上传请求

 常见的响应状态码

200    OK                     请求成功。一般用于GET与POST请求
201 Created                已创建。成功请求并创建了新的资源
401 Unauthorized           未授权/请求要求用户的身份认证
404 Not Found              服务器无法根据客户端的请求找到资源
500 Internal Server Error  服务器内部错误,无法完成请求

不同类型的请求及其作用

1. GET: 从服务器端读取数据
2. POST: 向服务器端添加新数据
3. PUT: 更新服务器端已经数据
4. DELETE: 删除服务器端数据

API 的分类

REST API: restful (Representational State Transfer (资源)表现层状态转化)
(1) 发送请求进行CRUD 哪个操作由请求方式来决定
(2) 同一个请求路径可以进行多个操作
(3) 请求方式会用到GET/POST/PUT/DELETE
非REST API: restless
(1) 请求方式不决定请求的CRUD 操作
(2) 一个请求路径只对应一个操作
(3) 一般只有GET/POST

测试: 可以使用json-server快速搭建模拟的rest api 接口

2.json-server使用

npm install -g json-server

目标根目录下创建数据库 json 文件:db.json

{
	"posts": [
		{ "id": 1, "title": "json-server", "author": "typicode" },
		{ "id": 2, "title": "json-server2", "author": "typicode" }
	],
	"comments": [
		{ "id": 1, "body": "some comment", "postId": 1 }
	],
	"profile": { "name": "typicode" }
}

启动服务器执行命令

 json-server --watch db.json

3 xhr的理解和使用

1. 使用 XMLHttpRequest (XHR) 对象可以与服务器交互 , 也就是发送 ajax 请求
2. 前端可以获取到数据,而无需让整个的页面刷新。
3. 这使得 Web 页面可以只更新页面的局部,而不影响用户的操作。

区别一般 http 请求与 ajax 请求

1. ajax 请求是一种特别的 http 请求
2. 对服务器端来说 , 没有任何区别 , 区别在浏览器端
3. 浏览器端发请求 : 只有 XHR fetch 发出的才是 ajax 请求 , 其它所有的都是
ajax 请求
4. 浏览器端接收到响应
(1) 一般请求 : 浏览器一般会直接显示响应体数据 , 也就是我们常说的刷新 /
跳转页面
(2) ajax 请求 : 浏览器不会对界面进行任何更新操作 , 只是调用监视的回调
函数并传入响应相关数据

xhrAPI

  • 1. XMLHttpRequest(): 创建 XHR 对象的构造函数
  • 2. status: 响应状态码值, 比如 200, 404
  • 3. statusText: 响应状态文本
  • 4. readyState: 标识请求状态的只读属性
        0: 初始
        1: open()之后
        2: send()之后
        3: 请求中
        4: 请求完成
  • 5. onreadystatechange: 绑定 readyState 改变的监听
  • 6. responseType: 指定响应数据类型, 如果是'json', 得到响应后自动解析响应体数据
  • 7. response: 响应体数据, 类型取决于 responseType 的指定
  • 8. timeout: 指定请求超时时间, 默认为 0 代表没有限制
  • 9. ontimeout: 绑定超时的监听
  • 10. onerror: 绑定请求网络错误的监听
  • 11. open(): 初始化一个请求, 参数为: (method, url[, async])
  • 12. send(data): 发送请求
  • 13. abort(): 中断请求
  • 14. getResponseHeader(name): 获取指定名称的响应头值
  • 15. getAllResponseHeaders(): 获取所有响应头组成的字符串
  • 16. setRequestHeader(name, value): 设置请求头

4 使用XHR 封装一个简单版axios

axios特点

  • 函数的返回值为promise, 成功的结果为response, 失败的结果为error
  • 能处理多种类型的请求: GET/POST/PUT/DELETE
  • 函数的参数为一个配置对象
    {
    	url: '', // 请求地址
    	method: '', // 请求方式GET/POST/PUT/DELETE
    	params: {}, // GET/DELETE 请求的 query 参数
    	data: {}, // POST/PUT 请求的请求体参数
    }
    

  • 响应 json数据 自动解析为 js的对象/数组

 简单axios编码实现

function axios({
            url,
            methed = 'GET',
            params = {},
            data = {}
        }) {
            //返回一个premise对象
            return new Promise((resolve, reject) => {
                // 执行异步Ajax请求

                //处理method(转为大写)
                methed = methed.toUpperCase()

                /* 
                {
                    id: 1,
                    xxx:'abc'
                }
                */
                //处理query参数(拼接到url上)  id=1&xxx=abc
                let queryString = ''
                Object.keys(params).forEach(key => {
                    queryString += `${key}=${params[key]}&`
                })
                if (queryString) {//id=1&xxx=abc&
                    //去除最后的&
                    queryString = queryString.substring(0, queryString.length - 1)
                    //拼接到url上
                    url += '?' + queryString
                }


                //创建xhr对象
                const request = new XMLHttpRequest()
                //打开连接(初始化请求)
                request.open(methed, url, true)

                //绑定状态改变的监听
                request.onreadystatechange = function () {
                    //如果请求没有完成,直接结束
                    if (request.readyState !== 4) {
                        return
                    }
                    //如果响应状态码在200到299之间代表成功 否则失败
                    const { status, statusText } = request
                    //如果请求成功调用resolve()
                    if (status >= 200 & status <= 299) {
                        //准备结果对象
                        const response = {
                            data: JSON.parse(request.response),//响应json数据自动解析为js的对象/数组
                            status,
                            statusText
                        }
                        resolve(response)
                    } else {//如果请求失败调用reject()
                        reject(new Error('request error status is ' + status))
                    }

                }

                //发送请求
                if (methed === 'GET' || methed === 'DELETE') {
                    request.send()
                } else if (methed === 'POST' || methed === 'PUT') {

                    request.setRequestHeader('Content-Type', 'application/json;charset=utf-8')//告诉服务器请求体的格式是json
                    request.send(JSON.stringify(data))//发送json格式请求体参数  send异步
                }

            })
        }

使用测试

// 1. GET请求:从服务器端获取数据
function testGet() {
  axios({
    url: 'http://localhost:3000/posts',
    method: 'GET',
    params:{
      id: 1,
      xxx: 'abc'
    }
  }).then(
    response => {
      console.log(response)
    },
    error => {
      alert(error.message)
    }
  )
}

// 2. POST请求:向服务器端添加数据
function testPost() {
  axios({
    url: 'http://localhost:3000/posts',
    method: 'POST',
    data: {
      "title": "json-server_post",
      "author": "typicode_post"
    }
  }).then(
    response => {
      console.log(response)
    },
    error => {
      alert(error.message)
    }
  )
}
// 3. PUT请求:服务器更新数据
function testPut() {
  axios({
    url: 'http://localhost:3000/posts/1',
    method: 'PUT',
    data: {
      "title": "json-server_put",
      "author": "typicode_put"
    }
  }).then(
    response => {
      console.log(response)
    },
    error => {
      alert(error.message)
    }
  )
}

// 3. DELETE请求:服务器删除数据
function testDelete() {
  axios({
    url: 'http://localhost:3000/posts/2',
    method: 'delete'
  }).then(
    response => {
      console.log(response)
    },
    error => {
      alert(error.message)
    }
  )
}

5 axios的理解和使用

特点

基于promise的封装XHR的异步ajax请求库
浏览器端/node端都可以使用
支持请求/响应拦截器
支持请求取消
请求/响应数据转换
批量发送多个请求

常用语法

axios(config): 通用/最本质的发任意类型请求的方式
axios(url[, config]): 可以只指定url发get请求
axios.request(config): 等同于axios(config)
axios.get(url[, config]): 发get请求
axios.delete(url[, config]): 发delete请求
axios.post(url[, data, config]): 发post请求
axios.put(url[, data, config]): 发put请求

axios.defaults.xxx: 请求的默认全局配置
axios.interceptors.request.use(): 添加请求拦截器
axios.interceptors.response.use(): 添加响应拦截器

axios.create([config]): 创建一个新的axios(它没有下面的功能)

axios.Cancel(): 用于创建取消请求的错误对象
axios.CancelToken(): 用于创建取消请求的token对象
axios.isCancel(): 是否是一个取消请求的错误
axios.all(promises): 用于批量执行多个异步请求
axios.spread(): 用来指定接收所有成功数据的回调函数的方法

在这里插入图片描述

 难点语法的理解和使用

axios.create(config)

1. 根据指定配置创建一个新的 axios, 也就就每个新 axios 都有自己的配置
2. axios 只是没有取消请求和批量发请求的方法 , 其它所有语法都是一致的
3. 为什么要设计这个语法 ?
(1) 需求 : 项目中有部分接口需要的配置与另一部分接口需要的配置不太一
, 如何处理
(2) 解决 : 创建 2 个新 axios, 每个都有自己特有的配置 , 分别应用到不同要
求的接口请求中

实例

 

拦截器函数/ajax 请求/请求的回调函数的调用顺序

1. 说明 : 调用 axios() 并不是立即发送 ajax 请求 , 而是需要经历一个较长的流程
2. 流程 : 请求拦截器 2 => 请求拦截器 1 => ajax 请求 => 响应拦截器 1 =>
应拦截器 2 => 请求的回调
3. 注意 : 此流程是通过 promise 串连起来的 , 请求拦截器传递的是 config, 响应
拦截器传递的是 response
// 添加两个请求拦截器(回调函数)
axios.interceptors.request.use(
  config => {
    console.log('request interceptor1 onResolved()') // -----------2
    return config
  },
  error => {
    console.log('request interceptor1 onRejected()')
    return Promise.reject(error)
  }
)

axios.interceptors.request.use(
  config => {
    console.log('request interceptor2 onResolved()') // -----------1
    return config
  },
  error => {
    console.log('request interceptor2 onRejected()')
    return Promise.reject(error)
  }
)

// 添加两个响应拦截器
axios.interceptors.response.use(
  resopnse => {
    console.log('response interceptor1 onResolved()') // -----------3
    return resopnse
  },
  error => {
    console.log('response interceptor1 onRejected()')
    return Promise.reject(error)
  }
)

axios.interceptors.response.use(
  resopnse => {
    console.log('response interceptor2 onResolved()') // -----------4
    return resopnse
  },
  error => {
    console.log('response interceptor2 onRejected()')
    return Promise.reject(error)
  }
)

axios.get('http://localhost:3000/posts')
  .then(response => {
    console.log('data', response.data) //data Array(4) -------------5
  })
  .catch(error => {
    cosole.log('error', error.message)
  })

// request interceptor2 onResolved()
// request interceptor1 onResolved()
// response interceptor1 onResolved()
// response interceptor2 onResolved()
// data Array(4)

取消请求

1. 基本流程
配置 cancelToken 对象
缓存用于取消请求的 cancel 函数
在后面特定时机调用 cancel 函数取消请求
在错误回调中判断如果 error cancel, 做相应处理
2. 实现功能
点击按钮 , 取消某个正在请求中的请求
在请求一个接口前 , 取消前面一个未完成的请求
server.js
const express = require('express')
const cors = require('cors')

const app = express()

// 使用cors, 允许跨域
app.use(cors())
// 能解析urlencode格式的post请求体参数
app.use(express.urlencoded({ extended: false }))
// 能解析json格式的请求体参数
app.use(express.json())

app.get('/products1', (req, res) => {

  setTimeout(() => {
    res.send([
      { id: 1, name: 'product1.1' },
      { id: 2, name: 'product1.2' },
      { id: 3, name: 'product1.3' }
    ])
  }, 1000 + Math.random() * 2000);

})

app.get('/products2', (req, res) => {

  setTimeout(() => {
    res.send([{
      id: 1,
      name: 'product2.1'
    },
    {
      id: 2,
      name: 'product2.2'
    },
    {
      id: 3,
      name: 'product2.3'
    }
    ])
  }, 1000 + Math.random() * 2000);

})

app.listen(4000, () => {
  console.log('server app start on port 4000')
})
// 添加请求拦截器
axios.interceptors.request.use((config) => { // 只写一个成功的回调
  // 在准备发请求前,取消未完成的请求
  if (typeof cancel === 'function'){
    cancel('取消请求')
  }
  // 添加一个cancelToken的配置
  config.cancelToken = new axios.CancelToken(function executor(c){ // c是用于取消当前请求的函数
      // 保存取消函数,用于之后可能需要取消当前请求
      cancel = c;
    })
    return config
})

// 添加响应拦截器
axios.interceptors.response.use(
  response => { // 成功的回调
    cancel = null 
    return response
  },
  error => { // 失败的回调
//在错误回调中判断如果 error 是 cancel, 做相应处理 解决上一次请求异步回调清空cancel的问题

    if (axios.isCancel(error)){ // 请求取消的错误   
        console.log('请求取消的错误', error.message)
        // 中断promise链
        return new Promise(() => {})
    }else{ // 请求出错了
      cancel = null 
      // 将错误向下传递 
      // throw error
      return Promise.reject(error)
    }
  }
)

let cancel // 用于保存取消请求的函数
function getProducts1() {
  axios({
    url: 'http://localhost:4000/products1'
  }).then(
    response => {
      console.log('请求1成功了', response.data)
    },
    error => { // 只用处理请求失败的情况,取消请求的错误不用处理
      console.log('请求1失败了', error.message, error) 
    }
  )
}

function getProducts2() {
  axios({
      url: 'http://localhost:4000/products2'
  }).then(
    response => {
      console.log('请求2成功了', response.data)
    },
    error => {
      console.log('请求2失败了', error.message, error) 
    }
  )
}
function cancelReq() {
  if (typeof cancel === 'function'){
    cancel('强制取消请求')
  } else {
    console.log('没有可取消的请求')
  }
}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值