现代浏览器是一个囊括了数百个组件的操作系统,包括进程管理、安全沙箱、分层的优化缓存、JavaScript虚拟机、图形渲染和GPU管道、存储系统、传感器、音频和视频,网络机制等等。

在浏览器上运行的应用的性能。,取决于多个组件:解析、布局、HTML和CSS样的计算、JavaScript执行速度、渲染管道、网络相关的各层协议的配合。

浏览器API与协议_网络

资源与客户端状态缓存:

浏览器在分派请求之前,会自动检查资源缓存,满足条件的就返回资源的本地副本,如果资源不在本地缓存中,浏览器就会发送网络请求,将响应自动填充到缓存中,方便后续访问。

XMLHttpRequest

XMLHttpRequest是浏览器层面的API,可以让开发人员通过JavaScript实现数据传输。发送请求后,浏览器会帮助我们完成所有底层的链接管理、协议协商、HTTP请求格式化,以及更多工作,比如:

  • 浏览器管理着连接建立、套接字池和连接终止
  • 浏览器决定最佳的HTTP(S)传输协议(HTTP 1.0、1.x和2.0)
  • 浏览器处理HTTP缓存、重定向和内容类型协商
  • 浏览器保障安全、验证和隐私

开发者只需要发起请你去、管理进度、然后处理服务器返回的响应数据就好。

跨源资源共享(CORS)

同源:是应用的协议、域名和端口三个都保持一致。
因为浏览器保存用户的数据,比如认证令牌、Cookie以及其他私有元数据,这些数据不能泄露给其他的应用。

为解决这个问题,XHR的早期版本都限制应用只能执行同源请求

要是没有同源沙箱,那么就导致一个应用可以访问另一个应用的用户数据。

如果我们的应用需要访问另一个服务器的资源,同源策略就会带来一些麻烦。所以就有了跨源资源共享,CORS。

// 脚本来源:(http, example.com, 80)
var xhr = new XMLHttpRequest();
xhr.open('GET', '/resource.js'); ➊
xhr.onload = function() { ... };
xhr.send();

var cors_xhr = new XMLHttpRequest();
cors_xhr.open('GET', 'http://thirdparty.com/resource.js'); ➋
cors_xhr.onload = function() { ... };
cors_xhr.send();

发起跨域请求后,浏览器会自动追加受保护的Origin HTTP首部,包含了发出请求的来源。服务器也可以检查Origin首部,决定时候接受该请求,如果接受就返回Access-Control-Allow-Origin响应首部:

=> 请求
GET /resource.js HTTP/1.1
Host: thirdparty.com
Origin: http://example.com 
...

<= 响应
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com 
...

XMLHttpRequest可以传输文本数据,可以传输二进制数据。

事实上,浏览器可以自动为各种原生数据类型提供编码和解码服务,因此应用在直接将这些数据传给XHR时就已经编码/解码好了,反之亦然。浏览器可以自动解码的数据类型如下:

  1. ArrayBuffer:固定长度的二进制数据缓冲区。
  2. Blob:二进制大对象或不可变数据。
  3. Document:解析后得到的HTML文档
  4. JSON:简单数据结构的JavaScript对象
  5. Text:简单的文本字符串

浏览器可以根据http的context-type首部来判断适当的数据类型,比如把application/json响应解析为JSON对象。在代码中这样设置:

var xhr = new XMLHttpRequest();
xhr.open('GET', '/images/photo.webp');
xhr.responseType = 'blob'; 

xhr.onload = function() {
  if (this.status == 200) {
    var img = document.createElement('img');
    img.src = window.URL.createObjectURL(this.response); 
    img.onload = function() {
        window.URL.revokeObjectURL(this.src); 
    }
    document.body.appendChild(img);
  }
};

xhr.send();

这是把返回的数据类型设置为Blob,基于返回的对象创建唯一的对象URL并且设置为图片的src。图片加载完毕后立即释放对象。

通过XHR上传数据:

基本代码实例如下:

var xhr = new XMLHttpRequest();
xhr.open('POST','/upload');
xhr.onload = function() { ... };
xhr.send("text string"); 

var formData = new FormData(); 
formData.append('id', 123456);
formData.append('topic', 'performance');

var xhr = new XMLHttpRequest();
xhr.open('POST', '/upload');
xhr.onload = function() { ... };
xhr.send(formData); 

var xhr = new XMLHttpRequest();
xhr.open('POST', '/upload');
xhr.onload = function() { ... };
var uInt8Array = new Uint8Array([1, 2, 3]); ➍
xhr.send(uInt8Array.buffer);