IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 网安学习日志(4)JS基础总结(2)AJAX -> 正文阅读

[JavaScript知识库]网安学习日志(4)JS基础总结(2)AJAX

AJAX

概念

浏览器与服务器之间,采用 HTTP 协议通信。用户在浏览器地址栏键入一个网址,或者通过网页表单向服务器提交内容,这时浏览器就会向服务器发出 HTTP 请求。
简单来说AJAX就是客户端给服务端传消息的工具(前后端交互)
AJAX本身默认异步作为他的执行机制(也可以支持同步 取决于async的取值 false为同步 true为异步)

异步请求和同步请求的区别

同步请求:
1.发出请求后,浏览器本身不能做其他动作
2. 必须得等到请求完成返回数据之后,才会执行后续的代码,
3. JS在执行AJAX的时候,其他页面都处于不能执行(假死)状态
就等同于代码是排队执行的,只有当前面的完成了才能轮到后面的
默认异步:
1.异步请求就当发出请求的同时,浏览器可以继续做任何事,
2.Ajax发送请求并不会影响页面的加载与用户的操作 

AJAX以前使用的是XML格式,现在被JSON格式所替代

XMLHttpRequest对象

XMLHttpRequest对象是 AJAX 的主要接口,用于浏览器与服务器之间的通信。尽管名字里面有XMLHttp,它实际上可以使用多种协议(比如fileftp),发送任何格式的数据(包括字符串和二进制)。
我们通过一个实例来解析该对象的使用方法

var xhr = new XMLHttpRequest();
//XMLHttpRequest对象本身是一个构造函数 他可以通过new来进行生成

xhr.onreadystatechange = function()//readystate方法就是用于监听通信的状态的。
{
  // 通信成功时,状态值为4
  if (xhr.readyState === 4){
    if (xhr.status === 200){
      console.log(xhr.responseText);//即通信成功则输出报告
    } else {
      console.error(xhr.statusText);
    }
  }
};

xhr.onerror = function (e) {
  console.error(xhr.statusText);
};//onerror就是用来显示报错的

xhr.open('GET', '/endpoint', true);
//open方法用于指定建立连接的细节,例如这里的传输方式为get,true代表了异步传输
xhr.send(null);
//send方法后跟实际请求。如果为POST请求,这里的null就为指定的数据体

当得到了服务器返回的数据,AJAX不会刷新本页面,只会对当前页面进行更新
注:AJAX不能进行跨域请求,只能向同源网址(协议,域名,端口号都相同)发送HTTP请求

XMLHttpRequest 的实例属性

XMLHttpRequest.readyState

XMLHttpRequest.readyState返回一个整数,表示实例对象的当前状态。该属性只读。它可能返回以下值。

  • 0,表示 XMLHttpRequest 实例已经生成,但是实例的open()方法还没有被调用。
  • 1,表示open()方法已经调用,但是实例的send()方法还没有调用,仍然可以使用实例的setRequestHeader()方法,设定 HTTP 请求的头信息。
  • 2,表示实例的send()方法已经调用,并且服务器返回的头信息和状态码已经收到。
  • 3,表示正在接收服务器传来的数据体(body 部分)。这时,如果实例的responseType属性等于text或者空字符串,responseText属性就会包含已经收到的部分信息。
  • 4,表示服务器返回的数据已经完全接收,或者本次接收已经失败。
var xhr = new XMLHttpRequest();

if (xhr.readyState === 4) {
  // 请求结束,处理服务器返回的数据
} else {
  // 显示提示“加载中……”
}

上面代码中,xhr.readyState等于4时,表明脚本发出的 HTTP 请求已经完成。其他情况,都表示 HTTP 请求还在进行中。

XMLHttpRequest.onreadystatechange

XMLHttpRequest.onreadystatechange属性指向一个监听函数。readystatechange事件发生时(实例的readyState属性变化),就会执行这个属性。
具体例子已经在上面有过体现,我们一般用这个属性来监听AJAX的状态码是否为4(即是否是正常的)

XMLHttpRequest.response

XMLHttpRequest.response属性表示服务器返回的数据体(即 HTTP 回应的 body 部分)。它可能是任何数据类型,比如字符串、对象、二进制对象等等,具体的类型由XMLHttpRequest.responseType属性决定。该属性只读。

如果本次请求没有成功或者数据不完整,该属性等于null。但是,如果responseType属性等于text或空字符串,在请求没有结束之前(readyState等于3的阶段),response属性包含服务器已经返回的部分数据。

var xhr = new XMLHttpRequest();

xhr.onreadystatechange = function () {
  if (xhr.readyState === 4) {
    handler(xhr.response);
  }
}

在这里插入图片描述

XMLHttpRequest.responseType

是字符串,表示服务器返回的数据额类型(可在open方法之后,send方法之前设置)
XMLHttpRequest.responseType属性可以等于以下值。

  • “”(空字符串):等同于text,表示服务器返回文本数据。//适用于大多数情况
  • “arraybuffer”:ArrayBuffer 对象,表示服务器返回二进制数组。
  • “blob”:Blob 对象,表示服务器返回二进制对象。//图片文件
  • “document”:Document 对象,表示服务器返回一个文档对象。//html/xml文档文件
  • “json”:JSON 对象。
  • “text”:字符串。
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png', true);
xhr.responseType = 'blob';

xhr.onload = function(e) {
  if (this.status === 200) {
    var blob = new Blob([xhr.response], {type: 'image/png'});
    // 或者
    var blob = xhr.response;
  }
};

xhr.send();

上面这个例子就是代表返回的是一个图片文件

XMLHttpRequest.responseText

XMLHttpRequest.responseText属性返回从服务器接收到的字符串,该属性为只读。只有 HTTP 请求完成接收以后,该属性才会包含完整的数据。
简单来说就是把所有的收到的字符串都显示出来,我这里用火狐的一个页面来显示:
在这里插入图片描述

XMLHttpRequest.responseURL

XMLHttpRequest.responseURL属性是字符串,表示发送数据的服务器的网址。

XMLHttpRequest.status,XMLHttpRequest.statusText

XMLHttpRequest.status属性返回一个整数,表示服务器回应的 HTTP 状态码。一般来说,如果通信成功的话,这个状态码是200;如果服务器没有返回状态码,那么这个属性默认是200。请求发出之前,该属性为0。该属性只读。

  • 200, OK,访问正常
  • 301, Moved Permanently,永久移动
  • 302, Moved temporarily,暂时移动
  • 304, Not Modified,未修改
  • 307, Temporary Redirect,暂时重定向
  • 401, Unauthorized,未授权
  • 403, Forbidden,禁止访问
  • 404, Not Found,未发现指定网址
  • 500, Internal Server Error,服务器发生错误

基本上,只有2xx和304的状态码,表示服务器返回是正常状态。

if (xhr.readyState === 4) {
  if ( (xhr.status >= 200 && xhr.status < 300)
    || (xhr.status === 304) ) {
    // 处理服务器的返回数据
  } else {
    // 出错
  }
}

XMLHttpRequest.statusText属性返回一个字符串,表示服务器发送的状态提示。不同于status属性,该属性包含整个状态信息,比如“OK”和“Not Found”。在请求发送之前(即调用open()方法之前),该属性的值是空字符串;如果服务器没有返回状态提示,该属性的值默认为“OK”。该属性为只读属性。

事件监听属性

XMLHttpRequest 对象可以对以下事件指定监听函数。

  • XMLHttpRequest.onloadstart:loadstart 事件(HTTP 请求发出)的监听函数
  • XMLHttpRequest.onprogress:progress事件(正在发送和加载数据)的监听函数
  • XMLHttpRequest.onabort:abort 事件(请求中止,比如用户调用了abort()方法)的监听函数
  • XMLHttpRequest.onerror:error 事件(请求失败)的监听函数
  • XMLHttpRequest.onload:load 事件(请求成功完成)的监听函数
  • XMLHttpRequest.ontimeout:timeout 事件(用户指定的时限超过了,请求还未完成)的监听函数
  • XMLHttpRequest.onloadend:loadend 事件(请求完成,不管成功或失败)的监听函数

XMLHttpRequest.withCredentials

XMLHttpRequest.withCredentials属性是一个布尔值,表示跨域请求时,用户信息(比如 Cookie 和认证的 HTTP 头信息)是否会包含在请求之中,默认为false,即向example.com发出跨域请求时,不会发送example.com设置在本机上的 Cookie(如果有的话)。
如果需要跨域 AJAX 请求发送 Cookie,需要withCredentials属性设为true。注意,同源的请求不需要设置这个属性。

Cookie和Session

在这里插入图片描述HTTP 协议是一种无状态协议,即每次服务端接收到客户端的请求时,都是一个全新的请求,服务器并不知道客户端的历史请求记录;
Cookie和Session就是为了解决这个问题诞生的。

Session

在客户端第一次请求服务器的时候,服务器会生成一个Session对象,用于记录这次请求中的一些操作(例如你登录的用户名等等)
工作原理
在第一次请求的时候,服务器生成Session对象,并生成一个SessionID,并通过一个响应头的命令,要求客户端设置一个Cookie。
客户端收到响应后,会设置一个相应的Cookie(过期时间为这次会话消失)
接下来客户端每次向同一个网站发送请求时,请求头都会带上该 Cookie信息(包含 sessionId ), 然后,服务器通过读取请求头中的 Cookie 信息,获取名称为 JSESSIONID 的值,得到此次请求的 sessionId。

Cookie

Http协议中,Cookie用于判断两个请求是否来自于同一个浏览器(例如用户保持着登录的状态),由浏览器进行存储
Cookie分为浏览器Cookie和WebCookie两类。
工作过程
创建 Cookie
当接收到客户端发出的 HTTP 请求时,服务器可以发送带有响应的 Set-Cookie 标头,Cookie 通常由浏览器存储,然后将 Cookie 与 HTTP 标头一同向服务器发出请求。
会话 Cookies
会话 Cookie 有个特征,客户端关闭时 Cookie 会删除,因为它没有指定Expires或 Max-Age 指令。

但是,Web 浏览器可能会使用会话还原,这会使大多数会话 Cookie 保持永久状态,就像从未关闭过浏览器一样。
永久性 Cookies

永久性 Cookie 不会在客户端关闭时过期,而是在特定日期(Expires)或特定时间长度(Max-Age)外过期
简单来说,Cookie就是用来存储客户端的请求信息的,便于下次请求的发起。
更详细的Cookie内容将会在下一篇讲到

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/', true);
xhr.withCredentials = true;
xhr.send(null);

为了让这个属性生效,服务器必须显式返回Access-Control-Allow-Credentials这个头信息。

Access-Control-Allow-Credentials: true

withCredentials属性打开的话,跨域请求不仅会发送 Cookie,还会设置远程主机指定的 Cookie。反之也成立,如果withCredentials属性没有打开,那么跨域的 AJAX 请求即使明确要求浏览器设置 Cookie,浏览器也会忽略。

注意,脚本总是遵守同源政策,无法从document.cookie或者 HTTP 回应的头信息之中,读取跨域的 Cookie,withCredentials属性不影响这一点。

readyStateChange 事件

readyState属性的值发生改变,就会触发 readyStateChange 事件。

我们可以通过onReadyStateChange属性,指定这个事件的监听函数,对不同状态进行不同处理。尤其是当状态变为4的时候,表示通信成功,这时回调函数就可以处理服务器传送回来的数据。

progress 事件

上传文件时,XMLHttpRequest 实例对象本身和实例的upload属性,都有一个progress事件,会不断返回上传的进度。

var xhr = new XMLHttpRequest();

function updateProgress (oEvent) {
  if (oEvent.lengthComputable) {
    var percentComplete = oEvent.loaded / oEvent.total;
  } else {
    console.log('无法计算进展');
  }
}

xhr.addEventListener('progress', updateProgress);

xhr.open();

load 事件、error 事件、abort 事件

load 事件表示服务器传来的数据接收完毕,error 事件表示请求出错,abort 事件表示请求被中断(比如用户取消请求)。

var xhr = new XMLHttpRequest();

xhr.addEventListener('load', transferComplete);
xhr.addEventListener('error', transferFailed);
xhr.addEventListener('abort', transferCanceled);

xhr.open();

function transferComplete() {
  console.log('数据接收完毕');
}

function transferFailed() {
  console.log('数据接收出错');
}

function transferCanceled() {
  console.log('用户取消接收');
}

loadend 事件

abortloaderror这三个事件,会伴随一个loadend事件,表示请求结束,但不知道其是否成功。

xhr.addEventListener('loadend', loadEnd);

function loadEnd(e) {
  console.log('请求结束,状态未知');
}

timeout 事件

服务器超过指定时间还没有返回结果,就会触发 timeout 事件,具体的例子参见timeout属性一节。

Navigator.sendBeacon()

用户卸载网页的时候,有时需要向服务器发一些数据。很自然的做法是在unload事件或beforeunload事件的监听函数里面,使用XMLHttpRequest对象发送数据。但是,这样做不是很可靠,因为XMLHttpRequest对象是异步发送,很可能在它即将发送的时候,页面已经卸载了,从而导致发送取消或者发送失败。

解决方法就是unload事件里面,加一些很耗时的同步操作。这样就能留出足够的时间,保证异步 AJAX 能够发送成功。

function log() {
  let xhr = new XMLHttpRequest();
  xhr.open('post', '/log', true);
  xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  xhr.send('foo=bar');
}

window.addEventListener('unload', function(event) {
  log();

  // a time-consuming operation
  for (let i = 1; i < 10000; i++) {
    for (let m = 1; m < 10000; m++) { continue; }
  }
});

上面代码中,强制执行了一次双重循环,拖长了unload事件的执行时间,导致异步 AJAX 能够发送成功。

类似的还可以使用setTimeout。下面是追踪用户点击的例子。

// HTML 代码如下
// <a id="target" href="https://baidu.com">click</a>
const clickTime = 350;
const theLink = document.getElementById('target');

function log() {
  let xhr = new XMLHttpRequest();
  xhr.open('post', '/log', true);
  xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  xhr.send('foo=bar');
}

theLink.addEventListener('click', function (event) {
  event.preventDefault();
  log();

  setTimeout(function () {
    window.location.href = theLink.getAttribute('href');
  }, clickTime);
});

上面代码使用setTimeout,拖延了350毫秒,才让页面跳转,因此使得异步 AJAX 有时间发出。

这些做法的共同问题是,卸载的时间被硬生生拖长了,后面页面的加载被推迟了,用户体验不好。

为了解决这个问题,浏览器引入了Navigator.sendBeacon()方法。这个方法还是异步发出请求,但是请求与当前页面线程脱钩,作为浏览器进程的任务,因此可以保证会把数据发出去,不拖延卸载流程。

window.addEventListener('unload', logData, false);

function logData() {
  navigator.sendBeacon('/log', analyticsData);
}

Navigator.sendBeacon方法接受两个参数,第一个参数是目标服务器的 URL,第二个参数是所要发送的数据(可选),可以是任意类型(字符串、表单对象、二进制对象等等)。

navigator.sendBeacon(url, data)

这个方法的返回值是一个布尔值,成功发送数据为true,否则为false

该方法发送数据的 HTTP 方法是 POST,可以跨域,类似于表单提交数据。它不能指定回调函数。

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-01-08 13:54:34  更:2022-01-08 13:56:58 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:41:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码