XMLHttpRequest详解

写在前面

主要梳理了一些通用方法之类的,比较有用的内容是CORS protocol,这部分的内容主要参考了fetch在whatwg的文档

历史

XHR对象是用来获取网络资源的一个对象,其名字是历史性原因并不代表其功能。XHR对象最初是WHATWG的HTML定义的一部分。2006年移到了W3C中,其扩展(例如:progress events、cross-origin requests)写在了另一草案中(XHR Level2)。到2011年两份定义汇总到了一起成为了标准文档并重新回到了WHATWG。

Interface XMLHttpRequest

// 事件接口
interface XMLHttpRequestEventTarget : EventTarget {
  // event handlers
  attribute EventHandler onloadstart;
  attribute EventHandler onprogress;
  attribute EventHandler onabort;
  attribute EventHandler onerror;
  attribute EventHandler onload;
  attribute EventHandler ontimeout;
  attribute EventHandler onloadend;
};
// responseType枚举值
enum XMLHttpRequestResponseType {
  "", "arraybuffer", "blob", 
  "document", "json", "text"
};

interface XMLHttpRequest : XMLHttpRequestEventTarget {
  // event handler
  attribute EventHandler onreadystatechange;

  // states
  const unsigned short UNSENT = 0;
  const unsigned short OPENED = 1;
  const unsigned short HEADERS_RECEIVED = 2;
  const unsigned short LOADING = 3;
  const unsigned short DONE = 4;
  readonly attribute unsigned short readyState;

  // request
  void open(ByteString method, USVString url);
  void open(ByteString method, USVString url, boolean async, optional USVString? username = null, optional USVString? password = null);
  void setRequestHeader(ByteString name, ByteString value);
           attribute unsigned long timeout;
           attribute boolean withCredentials;
  [SameObject] readonly attribute XMLHttpRequestUpload upload;
  void send(optional (Document or BodyInit)? body = null);
  void abort();

  // response
  readonly attribute USVString responseURL;
  readonly attribute unsigned short status;
  readonly attribute ByteString statusText;
  ByteString? getResponseHeader(ByteString name);
  ByteString getAllResponseHeaders();
  void overrideMimeType(DOMString mime);
           attribute XMLHttpRequestResponseType responseType;
  readonly attribute any response;
  readonly attribute USVString responseText;
  [Exposed=Window] readonly attribute Document? responseXML;
}

垃圾回收

当XHR对象的state是opend/headers received/loading或者有事件监听器在readystatechange/progress/abort/error/load/timeout/loadend上时都不会被回收(注:但基于JavaScript的垃圾回收机制,当XHR对象是unreachable的时候也会被回收)

事件

loadstart/progress/abort/error/load/timeout/loadend这些集成与XMLHttpRequestEventTarget,readystatechange来自XMLHttpRequest对象本身

状态

分为五个状态:unsent 0 / opened 1 / headers received 2 / loading 3 / done 4(XHR.readyState)

  • 我们判断请求是否完成就依靠这个状态值

Request

XHR对象有open/setRequestHeader/send/abort方法、timeout/withCredentials/upload/属性

  • withCredentials控制是否在发送请求时携带credentials,参考注1

Response

XHR对象有responseURL/status/statusText/responseType/response/responseText/responseXML属性、getResponseHeader/getAllResponseHeaders/overrideMimeType方法

  • 其中status和readyState是我们判断请求情况的两个依赖值;
  • responseType枚举:""、“arraybuffer”、“text”、“blob”、“document”、“json”、“text”
  • overrideMimeType强制服务器返回的response带有指定的"Content-Type"header

Interface FormData

interface FormData {
  void append(USVString name, USVString value);
  void append(USVString name, Blob blobValue, optional USVString filename);
  void delete(USVString name);
  FormDataEntryValue? get(USVString name);
  sequence<FormDataEntryValue> getAll(USVString name);
  boolean has(USVString name);
  void set(USVString name, USVString value);
  void set(USVString name, Blob blobValue, optional USVString filename);
  iterable<USVString, FormDataEntryValue>;
};

append(name, value/blobValue [, filename] ):根据name和value添加一个值;
delete(name):根据name删除一个值;
get(name):获取name下的第一个添加进去的值;
getAll(name):获取name下的所有值;
has(name):当name存在时返回true,否则返回false;
set(name, value/blobValue [,filename]):对name对应的值进行set,会把此前的值清空;

Interface ProgressEvent

interface ProgressEvent : Event {
  readonly attribute boolean lengthComputable;
  readonly attribute unsigned long long loaded;
  readonly attribute unsigned long long total;
};

loadstart事件后会多次触发,可以读取其中的loaded/total算出总进度

安全策略CORS protocol

为了跨域分享资源,允许比HTML表单更多样化的提起,所以有了CORS protocol。

CORS protocol由众多的标示response可跨域 http header 组成。对于request可能类型远多于HTML form表单,所以一个CORS-preflight request会先发出OPTIONS请求以确保当前的URL是否支持CORS protocol。

HTTP requests

CORS request是包含Origin头的HTTP协议,但这并不能够认为所有包含Origin头的请求都是CORS request,因为GET/HEAD意外的请求也都包含Origin头。
CORS-preflight request会包含Access-Control-Request-Method(指示对于CORS request将会使用哪一种method来获取资源)和Access-Control-Request-Headers(指示CORS request将会使用哪一些http headers)

HTTP responses

Access-Control-Allow-Origin:指出这个response是否能够跨域共享,返回请求头里的Origin的value或者’*’;
Access-Control-Allow-Credentials:指出当request’s credentials mode[注1]是’include’时response是否能被跨域共享,值’true’;
Access-Control-Allow-Methods:指出response资源在CORS protocol中一共支持哪些方法;
Access-Control-Allow-Headers:指出response资源在CORS protocol中一个工支持哪些头;
Access-Control-Max-Age:指出response资源在CORS protocol中能够被缓存多久;
Access-Control-Expose-Headers:指出response header头中哪些头可以被client获取到(default:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma)

// request
Access-Control-Request-Method = 'GET,POST'
Access-Control-Request-Headers = 'accept'
// response
Access-Control-Allow-Origin = origin-or-null / '*'
Access-Control-Allow-Credentials = 'true' (大小写敏感)
Access-Control-Allow-Methods = 'GET,OPTIONS,POST'
Access-Control-Allow-Headers = 'accept,Content-Type'
CORS protocol and credentials 跨域和凭证

假如www.a.com发起跨域请求,下面有个表来标示资源到底是否能被跨域共享

请求 credentials modeAccess-Control-Allow-OriginAccess-Control-Allow-Credentials是否共享
‘omit’‘*’Omitted
‘omit’‘*’‘true’
‘omit’https://www.a.com/Omitted不应该带有末尾的’/’
‘omit’https://www.a.comOmitted
‘inclued’‘*’‘true’如果credentials mode是include那么Access-Control-Allow-Origin头就不能是’*’
‘inclued’'‘https://www.a.com‘true’
‘inclued’'‘https://www.a.com‘True’大小写敏感

  1. credentials mode:共有三个值’omit’-发送请求时不允许携带任何credentials(凭证:cookie),'same-orgin’发送请求时允许携带同源credentials,'include’发送请求时总是携带所有credentials。这是一个定义在Fetch中的内容Fetch中由Request的credentials值决定,XHR中withCredentials属性与此类似。

参考

  1. xhr-whatwg
  2. fetch-whatwg

扩展资料

  1. javascript的垃圾回收
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值