网络请求前端

早期的网页

:早期的网页是由后端来渲染的(服务器端渲染 SSR)

  • 客户端发出请求 =》 服务端接收并返回HTML文档 =》 页面刷新客户端加载新的HTMl文档

什么是http?

  • 超文本传输协议,是一种分布式,协作式和超媒体信息系统的应用层协议;
  • Http是玩维网的数据通讯基础,设计http最初是为了提供一种发布和接收HTML页面的方法;
  • 通过HTTP或者HTTPS协议请求的资源由统一的标识符(URL)来标识

http是一个客户端(用户)和服务端(网站)之间请求和响应的标准

  • 通过使用网页浏览器,网络爬虫或者其他的工具,客户端发起一个http请求到服务器的端口(默认80端口)我们称这个客户端用户代理程序
  • 响应的服务器上存储一些资源 如HTML文件跟图片等,我们称这个响应服务器为源服务器。

HTTP的组成

一次HTTP请求主要包括:请求(Request) 响应(Response)

 HTTP版本

◼ HTTP/0.9
 发布于1991年;
 只支持GET请求方法获取文本数据,当时主要是为了获取HTML页面内容;
◼ HTTP/1.0
 发布于1996年;
 支持POST、HEAD等请求方法,支持请求头、响应头等,支持更多种数据类型(不再局限于文本数据) ;
 但是浏览器的每次请求都需要与服务器建立一个TCP连接,请求处理完成后立即断开TCP连接,每次建立连接增加了性能损耗;
◼ HTTP/1.1(目前使用最广泛的版本)
 发布于1997年;
 增加了PUT、DELETE等请求方法;
 采用持久连接(Connection: keep-alive),多个请求可以共用同一个TCP连接;
◼ 2015年,HTTP/2.0
◼ 2018年,HTTP/3.0

HTTP的请求的方式

◼ 在RFC中定义了一组请求方式,来表示要对给定资源执行的操作:

  1.  GET:GET 方法请求一个指定资源的表示形式,使用 GET 的请求应该只被用于获取数据。
  2.  HEAD:HEAD 方法请求一个与 GET 请求的响应相同的响应,但没有响应体。
  3. ✓ 比如在准备下载一个文件前,先获取文件的大小,再决定是否进行下载;
  4.  POST:POST 方法用于将实体提交到指定的资源。
  5.  PUT:PUT 方法用请求有效载荷(payload)替换目标资源的所有当前表示;
  6.  DELETE:DELETE 方法删除指定的资源;
  7.  PATCH:PATCH 方法用于对资源应部分修改;
  8.  CONNECT:CONNECT 方法建立一个到目标资源标识的服务器的隧道,通常用在代理服务器,网页开发很少用到。
  9.  TRACE:TRACE 方法沿着到目标资源的路径执行一个消息环回测试。

◼ 在开发中使用最多的是GET、POST请求;
 在后续的后台管理项目中,我们也会使用PATCH、DELETE请求;

HTTP Request Header

在request对象的header中也包含很多有用的信息,客户端会默认传递过来一些信息:

 

content-type是这次请求携带的数据的类型:

  •  application/x-www-form-urlencoded:表示数据被编码成以 '&' 分隔的键 - 值对,同时以 '=' 分隔键和值
  •  application/json:表示是一个json类型;
  •  text/plain:表示是文本类型;
  •  application/xml:表示是xml类型;
  •  multipart/form-data:表示是上传文件;

◼ content-length:文件的大小长度
◼ keep-alive:
         http是基于TCP协议的,但是通常在进行一次请求和响应结束后会立刻中断;
         在http1.0中,如果想要继续保持连接:
                ✓ 浏览器需要在请求头中添加 connection: keep-alive;
                ✓ 服务器需要在响应头中添加 connection:keey-alive;
                ✓ 当客户端再次放请求时,就会使用同一个连接,直接一方中断连接;
         在http1.1中,所有连接默认是 connection: keep-alive的;
                ✓ 不同的Web服务器会有不同的保持 keep-alive的时间;
                ✓ Node中默认是5s中;
◼ accept-encoding:告知服务器,客户端支持的文件压缩格式,比如js文件可以使用gzip编码,对应 .gz文件;
◼ accept:告知服务器,客户端可接受文件的格式类型;
◼ user-agent:客户端相关的信息;

HTTP Response响应状态码

Http状态码(Http Status Code)是用来表示Http响应状态的数字代码:
        
Http状态码非常多,可以根据不同的情况,给客户端返回不同的状态码;
MDN响应码解析地址: https://developer.mozilla.org/zh-CN/docs/web/http/status

 响应的header中包括一些服务器给客户端的信息:

Chrome安装插件-FeHelper

为了之后查看数据更加的便捷、优雅,我们安装一个Chrome插件:
方式一:可以直接通过 Chrome的扩展商店 安装;
方式二: 手动安装
下载地址: https://github.com/zxlie/FeHelper/tree/master/apps/static/screenshot/crx

AJAX发送请求

AJAX 是异步的 JavaScript 和 XML(Asynchronous JavaScript And XML)
         它可以使用 JSON XML HTML text 文本等格式发送和接收数据;
如何来完成 AJAX 请求呢?
         第一步:创建网络请求的 AJAX 对象(使用 XMLHttpRequest
         第二步:监听 XMLHttpRequest 对象状态的变化,或者监听 onload 事件(请求完成时发);
         第三步:配置网络请求(通过 open 方法);
         第四步:发送 send 网络请求;
      //1.创建XMLHttpRequest对象
      const xhr = new XMLHttpRequest();
      //2.监听对象状态的变化
      xhr.onreadystatechange = function () {
        console.log("状态发生了变化");
      };
      //3.配置请求的方式
      xhr.open("GET","http://192.168.0.110:1888/01_basic/hello_text")
      //4.发送请求
      xhr.send();
        

XMLHttpRequest的state(状态)

注意:这个状态并非是HTTP的相应状态,而是记录的XMLHttpRequest对象的状态变化。
         http响应状态通过status获取;
发送同步请求:
         将open的第三个参数设置为false
xhr.open("GET", "http://123.207.32.32:8000/home/multidata",false);

      //1.创建XMLHttpRequest对象
      const xhr = new XMLHttpRequest();
      //2.监听对象状态的变化
      xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
          console.log(xhr.response) 
          //JSON格式的字符串解析为一个JavaScript对象的代码
          console.log(JSON.parse(xhr.response));
        }
        console.log("状态发生了变化");
      };
      //3.配置请求的方式
      xhr.open("GET", "http://123.207.32.32:8000/home/multidata");
      //4.发送请求
      xhr.send();

XMLHttpRequest其他事件监听

除了onreadystatechange还有其他的事件可以监听
loadstart :请求开始。
progress : 一个响应数据包到达,此时整个 response body 都在 response 中。
abort :调用 xhr.abort() 取消了请求。
error :发生连接错误,例如,域错误。不会发生诸如 404 这类的 HTTP 错误。
load :请求成功完成。
timeout :由于请求超时而取消了该请求(仅发生在设置了 timeout 的情况下)。
loadend :在 load,error,timeout 或 abort 之后触发。
我们也可以使用load来获取数据
  //1.创建XMLHttpRequest对象
      const xhr = new XMLHttpRequest();
      //2.onload监听数据加载完成
      xhr.onload = function () {
        const res = JSON.parse(xhr.response);
       console.log(res);
      };
      //3.配置请求的方式
      xhr.open("GET", "http://123.207.32.32:8000/home/multidata",false);
      //4.发送请求
      xhr.send();

响应数据和响应类型

发送了请求后,我们需要获取对应的结果:response属性
         XMLHttpRequest response 属性 返回响应的正文内容;
         返回的类型取决于 responseType的属性 设置;
通过responseType可以设置获取数据的类型
         如果 将 responseType 的值设置为空字符串 ,则会使用 text 作为默认值。
        
   //3.告诉xhr获取到的数据类型
      xhr.responseType = "json";
      //1.创建XMLHttpRequest对象
      const xhr = new XMLHttpRequest();
      //2.监听对象状态的变化
      xhr.onload = function () {
        // const res = JSON.parse(xhr.response);
        console.log(xhr.response);
      };
      //3.告诉xhr获取到的数据类型
      xhr.responseType = "json";
      //4.配置请求的方式
      xhr.open("GET", "http://123.207.32.32:8000/home/multidata", false);
      //5.发送请求
      xhr.send();

和responseText、responseXML的区别:
         早期通常服务器返回的数据是 普通的文本和XML ,所以我们通常会通过responseText、         responseXML来获取响应结果;
         之后将它们转化成JavaScript对象形式;
         目前服务器基本返回的都是 json数据 ,直接设置为json即可;

HTTP响应的状态status

XMLHttpRequest的state是用于记录xhr对象本身的状态变化,并非针对于HTTP的网络请求状态。
如果我们希望获取HTTP响应的网络状态,可以通过status和statusText来获取:
      //1.创建XMLHttpRequest对象
      const xhr = new XMLHttpRequest();
      //2.监听对象状态的变化
      xhr.onload = function () {
        // const res = JSON.parse(xhr.response);
        console.log(xhr.response);
        console.log(xhr.status)//200
        console.log(xhr.statusText)//OK
      };
      //3.告诉xhr获取到的数据类型
      xhr.responseType = "json";
      //4.配置请求的方式
      xhr.open("GET", "http://123.207.32.32:8000/home/multidata");
      //5.发送请求
      xhr.send();

 GET/POST请求传递参数

在开发中,我们使用最多的是GET和POST请求,在发送请求的过程中,我们也可以传递给服务器数据。
常见的传递给服务器数据的方式有如下几种:
方式一 :GET请求的query参数
//1.创建XMLHttpRequest对象
      const xhr = new XMLHttpRequest();
      //2.数据加载完成后执行的回调函数
      xhr.onload = function () {
        console.log(xhr.response);
      };
      //3.告诉xhr获取到的数据类型
      xhr.responseType = "json";
      //4.配置请求的方式
      xhr.open(
        "GET",
        "http://123.207.32.32:1888/02_param/get?name=cui&age=18$address=重庆市"
      );
      //5.发送请求
      xhr.send();
方式二 :POST请求 x-www-form-urlencoded 格式
            //1.创建XMLHttpRequest对象
      const xhr = new XMLHttpRequest();
      //2.数据加载完成后执行的回调函数
      xhr.onload = function () {
        console.log(xhr.response);
      };
      //3.告诉xhr获取到的数据类型
      xhr.responseType = "json";
      //4.配置请求的方式
      xhr.open(
        "POST",
        "http://123.207.32.32:1888/02_param/posturl"
      );
      //发送请求体(body)
      xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
      //5.发送请求
      xhr.send("name=cui&age=18$address=重庆市");
方式三 :POST请求 FormData 格式
    <form action="">
      <input type="text" name="username" />
      <input type="password" name="password" />
    </form>
    <button class="btn">提交</button>
    <script>
      const btn = document.querySelector(".btn");
      const formEL = document.querySelector("form");
      btn.addEventListener("click", () => {
        // console.log(form);

        //1.创建XMLHttpRequest对象
        const xhr = new XMLHttpRequest();
        //2.数据加载完成后执行的回调函数
        xhr.onload = function () {
          console.log(xhr.response);
        };
        //3.告诉xhr获取到的数据类型
        xhr.responseType = "json";
        //4.配置请求的方式
        xhr.open("POST", "http://123.207.32.32:1888/02_param/postform");
        //发送请求体(body)
        // xhr.setRequestHeader(
        //   "Content-Type",
        //   "application/x-www-form-urlencoded"
        // );
        //5.发送请求
        const formdata = new FormData(formEL);

        xhr.send(formdata);
      });

方式四 :POST请求 JSON 格式
      //1.创建XMLHttpRequest对象
      const xhr = new XMLHttpRequest();
      //2.数据加载完成后执行的回调函数
      xhr.onload = function () {
        console.log(xhr.response);
      };
      //3.告诉xhr获取到的数据类型
      xhr.responseType = "json";
      //4.配置请求的方式
      xhr.open("POST", "http://123.207.32.32:1888/02_param/postjson");
      //发送请求体(body)
      xhr.setRequestHeader("Content-Type", "application/json");
      //5.发送请求
      xhr.send(JSON.stringify({ name: "崔", age: 18 }));

ajax网络请求封装

      function ajx({ url, methods = "GET", data = {}, success, failure } = {}) {
        const xhr = new XMLHttpRequest();
        xhr.onload = function () {
          if (xhr.status >= 200 && xhr.status < 300) {
            success && success(xhr.response);
          } else {
            failure && failure(xhr.status);
          }
        };
        //设置响应类型
        xhr.responseType = "json";
        const queryString = [];
        //拼接url参数
        if (methods.toUpperCase() === "GET") {
          for (let key in data) {
            queryString.push(`${key}=${data[key]}`);
          }
          url = url + "?" + queryString.join("&");
          //设置请求方式
          xhr.open(methods, url);
          //设置请求头
          xhr.setRequestHeader("Content-Type", "application/json");
          //发送请求
          xhr.send();
        } else {
          xhr.open(methods, url);
          //设置请求头
          xhr.setRequestHeader("Content-Type", "application/json");
          //发送请求
          xhr.send(JSON.stringify(data));
        }
      }
      ajx({
        url: "http://123.207.32.32:1888/02_param/get",
        success: function (res) {
          console.log(res);
        },
        data: { name: "崔", age: 18 },
        failure: function (res) {
          console.log(res);
        },
      });

以Promise方式返回(优化)

      function ajx({ url, methods = "GET", data = {}, success, failure } = {}) {
        return new Promise((resolve, reject) => {
          const xhr = new XMLHttpRequest();
          xhr.onload = function () {
            if (xhr.status >= 200 && xhr.status < 300) {
              resolve(xhr.response);
            } else {
              reject(xhr.status);
            }
          };
          //设置响应类型
          xhr.responseType = "json";
          const queryString = [];
          //拼接url参数
          if (methods.toUpperCase() === "GET") {
            for (let key in data) {
              queryString.push(`${key}=${data[key]}`);
            }
            url = url + "?" + queryString.join("&");
            //设置请求方式
            xhr.open(methods, url);
            //设置请求头
            xhr.setRequestHeader("Content-Type", "application/json");
            //发送请求
            xhr.send();
          } else {
            xhr.open(methods, url);
            //设置请求头
            xhr.setRequestHeader("Content-Type", "application/json");
            //发送请求
            xhr.send(JSON.stringify(data));
          }
        });
      }

      ajx({
        url: "http://123.207.32.32:1888/02_param/get",
        success: function (res) {
          console.log(res);
        },
        data: { name: "崔", age: 18 },
        failure: function (res) {
          console.log(res);
        },
      })
        .then((res) => console.log(res))
        .catch((err) => console.error(err));

延迟时间timeout和取消请求

当达到 超时时间后依然没有获取到数据 ,那么 这个请求会自动被取消掉
默认值为 0 ,表示没有设置超时时间;
我们也可以通过 abort 方法 强制取消请求;
 function ajx({ url, methods = "GET", data = {}, timeout, success, failure } = {}) {
        return new Promise((resolve, reject) => {
          const xhr = new XMLHttpRequest();
          xhr.timeout = timeout;
          xhr.onload = function () {
            if (xhr.status >= 200 && xhr.status < 300) {
              resolve(xhr.response);
            } else {
              reject(xhr.status);
            }
          };
          //设置响应类型
          xhr.responseType = "json";
          const queryString = [];
          //拼接url参数
          if (methods.toUpperCase() === "GET") {
            for (let key in data) {
              queryString.push(`${key}=${data[key]}`);
            }
            url = url + "?" + queryString.join("&");
            //设置请求方式
            xhr.open(methods, url);
            //设置请求头
            xhr.setRequestHeader("Content-Type", "application/json");
            //发送请求
            xhr.send();
          } else {
            xhr.open(methods, url);
            //设置请求头
            xhr.setRequestHeader("Content-Type", "application/json");
            //发送请求
            xhr.send(JSON.stringify(data));
          }
        });
      }

      ajx({
        url: "http://123.207.32.32:1888/01_basic/timeout",
        success: function (res) {
          console.log(res);
        },
        timeout: 2000,
        data: { name: "崔", age: 18 },
        failure: function (res) {
          console.log(res);
        },
      })
        .then((res) => console.log(res))
        .catch((err) => console.error(err));

如何通过封装的ajx取消请求,将xhr对象返回出去

      function ajx({ url, methods = "GET", data = {}, success, failure } = {}) {
        const xhr = new XMLHttpRequest();
        xhr.onload = function () {
          if (xhr.status >= 200 && xhr.status < 300) {
            success && success(xhr.response);
          } else {
            failure && failure(xhr.status);
          }
        };
        //设置响应类型
        xhr.responseType = "json";
        const queryString = [];
        //拼接url参数
        if (methods.toUpperCase() === "GET") {
          for (let key in data) {
            queryString.push(`${key}=${data[key]}`);
          }
          url = url + "?" + queryString.join("&");
          //设置请求方式
          xhr.open(methods, url);
          //设置请求头
          xhr.setRequestHeader("Content-Type", "application/json");
          //发送请求
          xhr.send();
        } else {
          xhr.open(methods, url);
          //设置请求头
          xhr.setRequestHeader("Content-Type", "application/json");
          //发送请求
          xhr.send(JSON.stringify(data));
        }
        return xhr;
      }
      const xhr = ajx({
        url: "http://123.207.32.32:1888/01_basic/timeout",
        success: function (res) {
          console.log(res);
        },
        data: { name: "崔", age: 18 },
        failure: function (res) {
          console.log(res);
        },
      });
      btn.addEventListener("click", () => {
        //取消网络请求
        xhr.abort();
      });

 promise封装的ajx,因为返回了有resolve,reject,将xhr赋值给Promise的xhr属性,再返回promise

      function ajx({
        url,
        methods = "GET",
        data = {},
        timeout,
        success,
        failure,
      } = {}) {
        const xhr = new XMLHttpRequest();
        const promise = new Promise((resolve, reject) => {
          xhr.timeout = timeout;
          xhr.onload = function () {
            if (xhr.status >= 200 && xhr.status < 300) {
              resolve(xhr.response);
            } else {
              reject(xhr.status);
            }
          };
          //设置响应类型
          xhr.responseType = "json";
          const queryString = [];
          //拼接url参数
          if (methods.toUpperCase() === "GET") {
            for (let key in data) {
              queryString.push(`${key}=${data[key]}`);
            }
            url = url + "?" + queryString.join("&");
            //设置请求方式
            xhr.open(methods, url);
            //设置请求头
            xhr.setRequestHeader("Content-Type", "application/json");
            //发送请求
            xhr.send();
          } else {
            xhr.open(methods, url);
            //设置请求头
            xhr.setRequestHeader("Content-Type", "application/json");
            //发送请求
            xhr.send(JSON.stringify(data));
          }
        });
        promise.xhr = xhr;
        return promise;
      }

      ajx({
        url: "http://123.207.32.32:1888/01_basic/timeout",
        success: function (res) {
          console.log(res);
        },
        timeout: 2000,
        data: { name: "崔", age: 18 },
        failure: function (res) {
          console.log(res);
        },
      })
        .then((res) => console.log(res))
        .catch((err) => console.error(err));

认识FetchFetch API

Fetch可以看做是早期的XMLHttpRequest的替代方案,它提供了一种更加现代的处理方案:
         比如 返回值是一个Promise ,提供了一种更加优雅的处理结果方式
         比如 不像XMLHttpRequest一样 ,所有的操作都在一个对象上;
fetch
        ✓ 在请求发送成功时,调用resolve回调then;
        ✓ 在请求发送失败时,调用reject回调catch;
函数的使用:
         input :定义要获取的资源地址,可以是一个URL字符串,也可以使用一个Request对象(实验性特性)类型;
         init :其他初始化参数
        ✓ method : 请求使用的方法,如 GET、POST;
        ✓ headers : 请求的头信息;
        ✓ body : 请求的 body 信息;

Fetch数据的响应(Response)

Fetch的数据响应主要分为两个阶段:
阶段一: 当服务器返回了响应( response
fetch 返回的 promise 就使用内建的 Response class 对象来对响应头进行解析;
在这个阶段,我们可以通过检查响应头,来检查 HTTP 状态以确定请求是否成功;
如果 fetch 无法建立一个 HTTP 请求,例如网络问题,亦或是请求的网址不存在,那么 promise 就会 reject
异常的 HTTP 状态,例如 404 500 ,不会导致出现 error
我们可以在 response 的属性中看到 HTTP 状态:
status HTTP 状态码,例如 200
ok :布尔值,如果 HTTP 状态码为 200-299 ,则为 true
第二阶段,为了获取 response body ,我们需要使用一个其他的方法调用。
response.text() —— 读取 response ,并以文本形式返回 response
response.json() —— response 解析为 JSON

Fetch网络请求的演练

    //   1.fech发起get请求
        fetch("http://123.207.32.32:8000/home/multidata")
          .then((res) => {
            //1.获取到response
            const response = res;
            //   2.获取具体的结果 response.json()返回一个Promise对象
            response.json().then((res) => {
              console.log(res);
            });
          })
          .catch((err) => {
            console.log(err);
          });

    //   优化一
      fetch("http://123.207.32.32:8000/home/multidata")
        .then((res) => {
          //1.获取到response
          const response = res;
          //   2.获取具体的结果 response.json()返回一个Promise对象
          return response.json();
        })
        .then((res) => console.log(res))
        .catch((err) => {
          console.log(err);
        });
      //优化二
      async function getData() {
        const response = await fetch(
          "http://123.207.32.32:8000/home/multidata"
        );
        const res = await response.json();
        console.log(res);
      }
      getData();

Fetch POST请求

创建一个 POST 请求,或者其他方法的请求,我们需要使用 fetch 选项:
         method :HTTP 方法,例如 POST,
         body :request body,其中之一:
        ✓ 字符串(例如 JSON 编码的),
        ✓ FormData 对象,以 multipart/form-data 形式发送数据,

 XMLHttpRequest文件上传

    <input type="file" />
    <button>上传</button>
    <script>
      const btn = document.querySelector("button");
      btn.addEventListener("click", () => {
        const fileEl = document.querySelector("input");
        console.log(fileEl.files);
        const formdata = new FormData();
        formdata.append("avatar", fileEl.files[0]);

        const file = fileEl[0];
        const xhr = new XMLHttpRequest();
        xhr.onload = () => {
          console.log(xhr.response);
        };
        xhr.open("POST", "http://123.207.32.32:1888/02_param/upload");
        xhr.send(formdata);
      });
    </script>
Fetch也支持文件上传,但是Fetch没办法监听进度。
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值