XMLHttpRequest

1. AJAX简介

Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

1.1. 特点

  • 在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。
  • 不需要任何浏览器插件,但需要用户允许 JavaScript 在浏览器上执行。

1.2. XMLHttpRequest

1.2.1. XMLHttpRequest简介

XMLHttpRequest 是实现 AJAX 的一种方式。
官网地址: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest

1.2.2. XMLHttpRequest实例与属性

  • 构造函数

let xhr = new XMLHttpRequest()

  • XMLHttpRequest.readyState (只读

XMLHttpRequest.readyState属性返回XMLHttpRequest客户端所处的状态。XHR客户端处于以下状态之一:
在这里插入图片描述示例代码

const xhr = new XMLHttpRequest();
console.log("UNSENT", xhr.readyState); // readyState will be 0

xhr.open("GET", "/api", true);
console.log("OPENED", xhr.readyState); // readyState will be 1

xhr.onprogress = () => {
  console.log("LOADING", xhr.readyState); // readyState will be 3
};

xhr.onload = () => {
  console.log("DONE", xhr.readyState); // readyState will be 4
};

xhr.send(null);
  • XMLHttpRequest.response (只读

XMLHttpReques实例的 response 属性以ArrayBufferBlobDocument、JavaScript对象或字符串的形式返回响应的主体内容,具体取决于请求的 responseType 属性的值。

  • XMLHttpRequest.responseText (只读

    返回一个字符串,该字符串以文本形式包含对请求的响应,如果请求未成功或尚未发送,则返回null。其他形式包括 XMLHttpRequest.responseXMLXMLHttpRequest.responseURL

  • XMLHttpRequest.responseType
  • XMLHttpRequest.status (只读

    只读的XMLHttpRequest.status属性返回XMLHttpRequest响应的数字HTTP状态代码。

  • XMLHttpRequest.timeout

    请求在自动终止之前可能花费的时间(以毫秒为单位)。

  • XMLHttpRequest.upload

    XMLHttpRequest.upload返回一个XMLHttpRequestUpload对象,可以观察该对象来监视上传的进度。
    它是一个不透明的对象,但因为它也是一个XMLHttpRequestEventTarget,所以可以附加事件侦听器来跟踪其进程。
    在这里插入图片描述

1.2.2. XMLHttpRequest方法

  • abort()

    如果请求已经发送,XMLHttpRequest.abort()方法会中止该请求。当请求中止时,其readyState将更改为XMLHttpRequest.UNSENT(0),并且请求的状态代码设置为0。

  • getAllResponseHeaders()

    返回值为一个字符串,由CRLF分隔的所有响应标头(字段名为Set Cookie的标头除外),如果未收到响应,则为null。如果发生网络错误,将返回一个空字符串。
    在这里插入图片描述

    getResponseHeader(headerName)
    const contentType = client.getResponseHeader("Content-Type");
    
  • open()

    初始化新创建的请求,或重新初始化现有请求

    open(method, url)
    open(method, url, async)
    open(method, url, async, user)
    open(method, url, async, user, password)
    
    • method
      要使用的HTTP请求方法,如“GET”、“POST”、“PUT”、“DELETE”等。对于非HTTP(S)URL忽略。
    • url
      一个字符串或任何其他带有字符串标识符URL的对象,它提供了发送请求的资源的URL。
    • async
      一个可选的布尔参数,默认为true,指示是否异步执行操作。如果该值为false,send()方法在收到响应之前不会返回。如果为true,则使用事件侦听器提供已完成事务的通知。如果multipart属性为true,则必须为true,否则将引发异常。
    • user, password
      用于身份验证的可选用户名;默认情况下,这是null值。
  • send()

    XMLHttpRequest.send()将请求发送到服务器。如果请求是异步的(这是默认的),则在发送请求并使用事件传递结果后,此方法立即返回。如果请求是同步的,则此方法在响应到达之前不会返回。send()接受一个可选参数,用于指定请求的主体;这主要用于PUT等请求。如果请求方法是GET或HEAD,则会忽略body参数,并将请求正文设置为null。如果使用setRequestHeader()未设置Accept标头,则会发送类型为“/”(任何类型)的Accept标头。

    send()
    send(body)
    
    body的取值
    
    • body可以是一个序列化的 Document

    • 一个 XMLHttpRequestBodyInit 根据Fetch规范,它可以是ArrayBufferBlobTypedArrayDataViewFormDataURLSearchParams字符串文字对象

    • null,默认值

    • note:发送二进制内容(例如文件上传)的最佳方式是将TypedArray、DataView或Blob对象与send()方法结合使用。
      返回值:None (undefined).

    报错信息:
    InvalidStateError DOMException
    如果已经为请求调用了send(),或请求已完成。
    NetworkError DOMException
    如果要获取的资源类型是Blob,并且方法不是GET。

  • setRequestHeader()

    必须在send()之前,open()方法之后调用,出于安全原因,有几个被禁止的请求头名称,其值由用户代理控制。任何从前端JavaScript代码为其中一个请求头设置值的尝试都将被忽略,不会发出警告或出现错误。此外,Authorization HTTP请求头名可以添加到请求中,但如果请求被跨源重定向,则会被删除。

    setRequestHeader(header, value)

1.2.3. XMLHttpRequest事件监听

EventEvent properties触发条件
abortlengthComputable,loaded,totalabort event 是在请求被中止时触发的,例如XMLHttpRequest实例调用 abort() 方法
errorlengthComputable,loaded,total当请求遇到错误时,会激发错误事件。
loadendlengthComputable,loaded,total当请求完成时,无论是成功(加载后)还是失败(中止或出错后),都会触发loadend事件
loadlengthComputable,loaded,total当XMLHttpRequest事务成功完成时,将触发加载事件。
loadstartlengthComputable,loaded,total当请求开始加载数据时,会触发loadstart事件。
progresslengthComputable,loaded,total当请求接收到更多数据时,会定期触发进度事件。
readystatechangelengthComputable,loaded,total只要XMLHttpRequest的readyState属性发生更改,就会触发readystatechange事件。
timeoutlengthComputable,loaded,total当进程由于预设时间到期而终止时,会触发超时事件。
  • lengthComputable:boolean,表示程序进程进度是否是可计算的(可测量的)。
  • loaded:64-bit unsigned integer,表示底层进程已执行的工作量。以完成工作比率可以通过将loaded / total计算。当使用HTTP下载资源时,loaded 只计算HTTP消息的正文,不包括请求头和其他开销。
  • total:64-bit unsigned integer,表示底层进程正在执行的总工作量。当使用HTTP下载资源时,total 只表示 Content-Length(消息正文的大小),不包括请求头和其他开销。
  • 语法示例:
    addEventListener("abort", (event) => {});
    onabort = (event) => {};
    addEventListener("error", (event) => {});
    onerror = (event) => {};
    

2. XMLHttpRequest Demo

2.1. Demo1 progress event

<div class="controls">
  <input
    class="xhr success"
    type="button"
    name="xhr"
    value="Click to start XHR (success)" />
  <input
    class="xhr error"
    type="button"
    name="xhr"
    value="Click to start XHR (error)" />
  <input
    class="xhr abort"
    type="button"
    name="xhr"
    value="Click to start XHR (abort)" />
</div>

<textarea readonly class="event-log"></textarea>
const xhrButtonSuccess = document.querySelector(".xhr.success");
const xhrButtonError = document.querySelector(".xhr.error");
const xhrButtonAbort = document.querySelector(".xhr.abort");
const log = document.querySelector(".event-log");

function handleEvent(e) {
  log.textContent = `${log.textContent}${e.type}: ${e.loaded} bytes transferred\n`;
}

function addListeners(xhr) {
  xhr.addEventListener("loadstart", handleEvent);
  xhr.addEventListener("load", handleEvent);
  xhr.addEventListener("loadend", handleEvent);
  xhr.addEventListener("progress", handleEvent);
  xhr.addEventListener("error", handleEvent);
  xhr.addEventListener("abort", handleEvent);
}

function runXHR(url) {
  log.textContent = "";

  const xhr = new XMLHttpRequest();
  addListeners(xhr);
  xhr.open("GET", url);
  xhr.send();
  return xhr;
}

xhrButtonSuccess.addEventListener("click", () => {
  runXHR(
    "https://raw.githubusercontent.com/mdn/content/main/files/en-us/_wikihistory.json",
  );
});

xhrButtonError.addEventListener("click", () => {
  runXHR("http://i-dont-exist");
});

xhrButtonAbort.addEventListener("click", () => {
  runXHR(
    "https://raw.githubusercontent.com/mdn/content/main/files/en-us/_wikihistory.json",
  ).abort();
});

2.1. Demo2 XMLHttpRequest 上传图片

<!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>
    <style>
        .image-upload{
            display:inline-block;
            position: relative;
        }
        .image-upload__input {
            display: none;
        }

        .image-upload__thumbnail {
            width: 100px;
            height: 100px;
            border: 1px solid black;
        }

        .image-upload__body {
            position: relative;
            display: inline-block;
            height: 100%;
        }

        .image-upload__background {
            position: absolute;
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
            background-color: rgba(0, 0, 0, 0.5);
        }
        .image-upload__progress{
            position: absolute;
            top:0;
            bottom:0;
            left:0;
            right:0;
            width: auto;
            margin: auto 0;
        }
        .is-not-uploading{
            display: none;
        }
    </style>
</head>

<body>
    <div class="image-upload">
        <label for="up-image" class="image-upload__body">
            <img alt="上传文件" id="image" src="缺省页_上传中.svg" class="image-upload__thumbnail">
            <div class="image-upload__background is-not-uploading">
                <progress class="image-upload__progress "></progress>
            </div>
        </label>
        <input id="up-image" type="file" accept="image/*" class="image-upload__input">
    </div>
    <script>
        let imageUploadThumbnail = document.querySelector('.image-upload__thumbnail');
        let imageUploadInput = document.querySelector('.image-upload__input');
        let imageUploadBackground = document.querySelector('.image-upload__background');
        let imageUploadProgress = document.querySelector('.image-upload__progress');
        imageUploadInput.onchange = function(){
            let formData = new FormData();
            let file = this.files[0];
            let xhr = new XMLHttpRequest();
            if(!file){
                return ;
            }
            formData.set('file',file);
            imageUploadThumbnail.src = URL.createObjectURL(file);//在控件内显示选中图片
            imageUploadBackground.classList.remove("is-not-uploading");
            xhr.upload.onprogress = function(e){
                imageUploadProgress.value = e.loaded;
                imageUploadProgress.max = e.total;
            };
            xhr.onloadend = function(){
                imageUploadThumbnail.src="缺省页_上传中.svg";
                imageUploadBackground.classList.add("is-not-uploading");
            }
            xhr.open("POST",'http://192.168.36.115:8080/common/upload');
            
            xhr.send(formData);
            console.log("请求发送中");
        }
    </script>
</body>



</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值