Skip to content
On this page

前后端交互

学习目标

  • 【了解】前后端分离的概念
  • 【了解】HTTP协议
  • 【掌握】Ajax的使用
  • 【掌握】Fetch的基本使用
  • 【掌握】接口测试工具的使用
  • 【了解】Restful接口风格
  • 【掌握】Axios的使用

前后端分离的概念

在当代web应用的开发中,前端和后端作为2个独立的岗位愈加区分开了工作职责,前端负责视图开发,后端负责数据开发,前后端通过一种"方式"实现交互,最终完成整个web应用。

p9k1K3D.png

这种开发模式的好处显而易见:

  • 提高开发效率: 前后端开发人员可是同时开发, 互不影响
  • 提高复用性: 后端通过统一的API提供数据, 这样可以同时为web前端/app前端/微信端提供数据

Http协议

我们刚才提到了前后端通过一种“方式”来进行交互,这种方式便是Http协议,Http是一种网络协议, 规定了web服务器与浏览器之前的交互方式, 是一种一问一答协议。

  • 由浏览器发起请求(request)

  • 由web服务器针对请求生成响应(response)

    p9k1H56.png

常见的http请求包括get请求和post请求:

  • get请求是从服务器上获取数据,可以直接通过浏览器输入URL来获得。
  • post请求是向服务器传送数据,无法通过浏览器URL直接实现。
  • get传送的数据量较小,不能大于2KB。
  • post请求的数据是放在请求体中的,存放的数据量不受限制。
  • get请求携带的参数直接暴露,安全性非常低。
  • post请求安全性相对较高。

对于http请求来说,可能会有多种响应结果,http状态码就是用来表示响应结果的:

  • 1xx:指示信息--表示请求已接收,继续处理。
  • 2xx:成功--表示请求已被成功接收、理解、接受。
  • 3xx:重定向--要完成请求必须进行更进一步的操作。
  • 4xx:客户端错误--请求有语法错误或请求无法实现。
  • 5xx:服务器端错误--服务器未能实现合法的请求。

常见的状态码:

  • 200 OK:客户端请求成功。
  • 400 Bad Request:客户端请求有语法错误,不能被服务器所理解。
  • 401 Unauthorized:请求未经授权,这个状态代码必须和WWW-Authenticate一起使用。
  • 403 Forbidden:服务器收到请求,但是拒绝提供服务。
  • 404 Not Found:请求资源不存在,举个例子:输入了错误的URL。
  • 500 Internal Server Error:服务器发生不可预期的错误。

Ajax的使用

了解了http请求后,我们现在应该关注一件事,如何通过JS代码来实现一个具体的http请求,首先我们来学习第一种方法,也是最常用的方法——AJAX。

AJAX = Asynchronous JavaScript And XML.

AJAX基于浏览器内建的 XMLHttpRequest 对象实现,Ajax 允许通过与Web 服务器交换数据来异步更新网页。这意味着可以更新网页的部分,而不需要重新加载整个页面。

p9kYepV.png

  1. 网页中发生一个事件(页面加载、按钮点击)
  2. 由 JavaScript 创建 XMLHttpRequest 对象
  3. XMLHttpRequest 对象向 web 服务器发送请求
  4. 服务器处理该请求
  5. 服务器将响应发送回网页
  6. 由 JavaScript 读取响应
  7. 由 JavaScript 执行正确的动作(比如更新页面)

现在我们把上述步骤转化为JS代码,这里需要明确一点,完成上面的流程我们还需要一个服务器接口,在当前课程阶段,我们可以找一个公共接口来实现,例如:API接口

我们现在调用 这个接口,将返回的中文内容渲染到页面上。

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>今天的励志是:</h1>
    <button onclick="init()">点我励志</button>
    <script>
      function init() {
        let xhr = new XMLHttpRequest()
        xhr.onreadystatechange = function () {
          if (this.readyState == 4 && this.status == 200) {
            document.querySelector('h1').innerHTML =JSON.parse(this.responseText).data.zh
          }
        }
        xhr.open("GET", "https://api.vvhan.com/api/en")
        xhr.send()
      }
    </script>
  </body>
</html>

这里我们需要关注的是onreadystatechange事件,它会监听readyState的状态值变化:

  • 0: 请求未初始化
  • 1: 服务器连接已建立
  • 2: 请求已接收
  • 3: 正在处理请求
  • 4: 请求已完成且响应已就绪

readyState4status200 时,我们可以认为这个http响应就绪,便可以获得服务端的数据了。

Ajax是JS中最为常见的异步场景,可以使用大家Promise进行进一步封装,大家思考一下上述案例如何利用Promise来进行优化呢?

Fetch的基本使用

除了Ajax,javascript还提供了一个全局方法fetch可以实现http请求,它返回一个Promise对象,通过2次调用.then方法可以获取到数据内容。上文中的案例可以使用fetch来进行改写:

js
function init() {
    fetch("https://api.vvhan.com/api/en").then(res=>{
        return res.json()
    }).then(res=>{
        document.querySelector('h1').innerHTML = res.data.zh
    })
}

在实际工作开发中,我们更多地使用Ajax来进行前后端交互,fetch的兼容性相对较差。

接口调试工具

我们刚才演示了使用JS代码来获取接口数据,但很多场景下,使用JS代码来测试接口相对麻烦,这时我们可以使用接口调试工具来实现,这类工具的使用方法基本一致,例如postman,apizza 以及更好支持中文的ApiPost等。

Restful接口风格

前后端分离的协作模式要求前端在调用接口,后端在设计接口时尽量保持一致,RESTful便是一种当前最流行的接口设计风格,主要包括以下方面:

  • 资源路径(URL)

    标准的RESTful API中, 每个资源路径对应一个唯一的资源

    所以规定网址中不能有动词, 只能有名词, 并且一般来说为复数.

    示例

  • HTTP动词(Method)

    对于资源, 一般有4个操作, CURD(增/删/改/查)

    • GET: 从服务器获取资源(一项或多项)
    • POST: 在服务器新建一个资源
    • PUT: 在服务器更新资源, 服务器返回完整的属性
    • DELETE: 从服务器删除资源
    • PATCH: 在服务器更新资源, 服务器只返回更新的属性

    示例

    • POST /articles -- 创建文章内容
    • GET /articles/1 -- 获取主键id为1的文章
  • 过滤信息(query-string)

    当服务端需要返回的数据很多时, 服务器不可能全部返回

    此时, 我们可以在客户端携带过滤信息, 比如: 分页信息

    示例

    • ?page=1 -- 第一页的信息
    • ?offset=10&per_page=10 -- 每页10条, 偏移10
  • 状态码(Status-code)

    服务端返回的信息, 用来告诉客户端操作结果

    状态码含义说明
    200OK操作成功, 并返回数据
    201CREATED新建成功
    204NO CONTENT删除成功
    400BAD REQUEST请求语法错误
    403Forbidden请求没有权限的资源
    404NOT FOUND没有找到请求的资源
  • 错误信息(Error)

    如果状态码是4xx或者5xx, 需要告诉客户端对应的错误信息. 以JSON格式返回

  • 返回结果(Result)

    针对不同的操作, 服务需要返回的结果应该符合这样的规范

    • GET /collections -- 返回资源列表(数组)
    • GET /collections/:id -- 返回单个资源 eg. /collections/1
    • POST /collections -- 返回新生成的资源
    • PUT /collections/:id -- 返回资源的完整属性
    • PATCH /collections/:id -- 返回被修改的属性
    • DELETE /collections/:id -- 返回204状态码+空文档

当然,实际接口的表现并非和RESTful完全一致,让前后端更好地沟通交流是接口设计的最终原则。

Axios的使用

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。是当前最为流行的http库,它之所以流行是得益于它的以下特性:

  • 从浏览器中创建 XMLHttpRequests
  • 从 node.js 创建 http 请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF

我们可以把axios理解为对AJAX的封装,使用起来会高效很多,一起来尝试看,

首先在当前页面中引入axios:

html
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

这样我们可以在全局获得一个axios函数,尝试使用它来发送一个请求:

js
axios.get('https://api.vvhan.com/api/en')

axios是基于Promise实现的,响应的结果保存到了Promise中,所以可以通过then方法中回调传入的参数来获取结果。

我们刚才发送get请求的方式是一种简写形式,完整的写法是这样的:

js
axios({
      method: 'GET',
      url: 'https://api.vvhan.com/api/en',
}).then((res) => console.log(res))

通过传入配置对象的形式来确认发送请求的类型,以及请求的URL,我们现在就对这个配置选项来做全面的学习。

配置选项

method

method是创建请求时的方法,常见的有get post put patch delete等,如果没有指定,默认为get。

url

url是用于请求的服务器url地址,这个配置选项是必需的,其他配置选项都有默认值。

baseURL

通过设置baseURL,可以提取url中重复的部分,例如:设置baseURL:https://api.vvhan.com/apiurl选项设置为/en即可。

data

data是请求中携带的数据。只适用于post put patch方法。data中携带数据的格式由后端来定义,前端根据接口文档来设置即可,一般即为普通对象。

timeout

请求超时的时间,如果请求超过了设定的timeout那么请求便会被中断。

params

发送get请求时携带的查询参数还可以通过params选项的形式传递,例如https://api.vvhan.com/api/en?type=sj中携带的参数可以写成params选项:

js
axios({
        method: 'GET',
        url: 'https://api.vvhan.com/api/en',
        params:{
            type:'sj'
        }
      })

headers

headers中可以配置请求的请求头信息,在登录认证中一般会在请求头中携带token信息。

响应对象

发送一个axios请求后,返回的结果有固定的结构,现在对这个结构加以说明:

js
{
  // `data` 表示服务器返回的具体数据
  data: {},

  // `status` 来自服务器响应的 HTTP 状态码
  status: 200,

  // `statusText` 来自服务器响应的 HTTP 状态信息
  statusText: 'OK',

  // `headers` 服务器的响应头信息
  headers: {},

   // `config` 是为请求提供的配置信息 即是我们传入的配置选项
  config: {},
  // `request` 是 发送请求的XHR对象
  request: {}
}

默认值

可以通过指定默认值的形式来给axios请求添加配置选项。

js
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.timeout = 3000;
每个axios请求会有默认值的baseURL和timeout

拦截器

http请求在发送和响应的过程可以被axios拦截器处理。在拦截器中可以进行额外的逻辑处理。

js
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么  这里有一个最常见的前端场景 就是给请求头中添加token信息
    config.headers.Authorization=AUTH_TOKEN
    return config;
  }, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  });

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    // 对响应数据做点什么 如果我们只需要响应的数据内容 可以返回response.data
    return response.data;
  }, function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
  });

通过以上对axios的学习,你能否自己来实现一个建议版的axios呢?

版权声明 鄂ICP备2022000216号-2