1. 前后应用从浏览器端向服务器发送HTTP请求(请求报文)
2. 后台服务器接收到请求后, 调度服务器应用处理请求, 向浏览器端返回HTTP响应(响应报文)
3. 浏览器端接收到响应, 解析显示响应体/调用监视回调
请求方式/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
status
statusText
Content-Type: text/html;charset=utf-8
Set-Cookie: BD_CK_SAM=1;path=/
html 文本/json 文本/js/css/图片...
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: 删除服务器端数据
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 接口
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
promise
, 成功的结果为response
, 失败的结果为error
- {
- url: '', // 请求地址
- method: '', // 请求方式GET/POST/PUT/DELETE
- params: {}, // GET/DELETE 请求的 query 参数
- data: {}, // POST/PUT 请求的请求体参数
- }
- 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)
- }
- )
- }
- 基于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.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)
- 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('没有可取消的请求')
- }
- }