JS 中的网络请求 AJAX, Fetch, WebSocket

AJAX 是 Asynchronous JavaScript And XML 的简称,它可让页面在不刷新的状况下从服务器获取数据。javascript

XMLHttpRequest

浏览器使用XMLHttpRequest对象于服务器通讯,它可使用JSON,XML,HTML和text等格式发送和接收数据。php

低版本 IE 浏览器没有XMLHttpRequest对象,可是它可使用ActiveXObject对象代替。java

if (window.XMLHttpRequest) { // IE7+
    XHR = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE 6
    XHR = new ActiveXObject("Microsoft.XMLHTTP");
}
复制代码

建立 XHR 实例事后就能够监听该实例的状态改变事件onreadystatechange,它会在 XHR 实例的readyState的值改变时触发回调函数。web

XHR.onreadystatechange = function () { }
复制代码

而后咱们就可使用open方法初始化一个请求和send方法发送 HTTP 请求。ajax

XHR.open('GET', 'http://q.com')

// open 方法一共有 5 个参数,method, url, async, user, password 后三个可选。
// async 表示此次是否异步请求,默认是 true

XHR.send()
// send 方法接受一个可选参数 请求主体。
// 参数能够是 FormData, FormData, ArrayBuffer, Document, 序列化字符串
复制代码

若是是post方法,就要在send以前设置请求头的Content-Typejson

httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')

// 它接受两个参数 header 和 value
复制代码

而后咱们就要处理服务器返回的数据,回到onreadystatechange函数。它监听readyState属性的变化,而它一共有 5 个值。跨域

  1. 0 表示 请求还未初始化,还没有调用 open() 方法。
  2. 1 表示 已创建服务器连接,open() 方法已经被调用。
  3. 2 表示 请求已接受,send() 方法已经被调用,而且头部和状态已经可得到。
  4. 3 表示 正在处理请求,下载中; responseText 属性已经包含部分数据。
  5. 4 表示 完成,下载操做已完成。

咱们还须要关心status属性它也是只读属性,它是此次响应中的 HTTP 数字状态码。在请求以前和 XMLHttpRequest 出错时它为0数组

responseText 属性是实际的数据,它是字符串,若是相应是 JSON 格式,须要用 JSON 的 parse 处理。浏览器

XHR.onreadystatechange = function () {
    if (XHR.readyState === 4 && XHR.status === 200) {
        console.log(JSON.parse(XHR.responseText))
    }
}
复制代码

若是服务器返回的是 XML, 咱们能够用responseXML属性得到数据。缓存

// 若是已指明,responseType 必须是空字符串或 "docuemnt" 
XHR.responseType = 'document';

// overrideMimeType() 用来强制解析 response 为 XML
XHR.overrideMimeType('text/xml');

// --------------

var root = XHR.responseXML.getElementsByTagName('root').item(0)
复制代码

responseType 属性是一个枚举类型的属性,返回响应数据的类型。

withCredentials 属性是一个Boolean类型,它指示了是否该使用相似cookies,authorization headers(头部受权)或者TLS客户端证书这一类资格证书来建立一个跨站点访问控制请求。

(在IE中,超时属性可能只能在调用 open() 方法以后且在调用 send() 方法以前设置)

abort方法用来终止请求

getAllResponseHeaders方法返回全部的响应头

getResponseHeader(name)方法返回包含指定头文本的字符串

XMLHttpRequset 2

XMLHttpRequset 2 增长了一些新功能。好比能发送FormData

超时时间

timeout 属性是超时时间,单位毫秒。当超时发生时他会触发ontimeout回调函数。

xhr.open('GET', '/server')

xhr.timeout = 2000

xhr.ontimeout = function (e) {}

xhr.send(null);
复制代码

还有 6 个进度事件。

  1. loadstart 在收到响应的第一个字节触发
  2. progress 在接收期间不断触发
  3. error 发生错误
  4. abort 调用abort方法而终止
  5. load 接收到完整数据
  6. loadend 在通讯完成或abort error load事件后触发

load事件就不用readystatechange事件和读取readyState属性。

xhr.addEventListener("progress", updateProgress, false);
xhr.addEventListener("load", transferComplete, false);
xhr.addEventListener("error", transferFailed, false);
xhr.addEventListener("abort", transferCanceled, false);

function updateProgress(event) {
  if (event.lengthComputable) {
    console.log(`${event.position} / ${event.totalSize}`)
  }
}
复制代码

其中progress的事件对象多了三个属性。

  1. lengthComputable 布尔值 表示进度信息是否可用
  2. position 已经接收到的字节数
  3. totalSize 根据Content-Length预期的字节数

跨域

同源策略限制了从同一个源加载的文档或脚本如何与来自另外一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。

当前网址(http://news.a.com)和请求网址

  1. https://news.a.com 不一样协议
  2. http://news.a.com:8080 不一样端口
  3. http://home.a.com 不一样域名

时就不是同源。

为了使 ajax 能够从不一样的网址获取数据。

咱们可使用跨域资源共享(CORS)来解决问题。

在发送请求时会有个Origin头表示请求页面的源信息, 若是服务器返回的Access-Control-Allow-Origin中有相同的源信息或是* 那么就能够跨域请求信息,请求和响应都不包含cookie

CORS经过Preflighted Requests透明服务器验证机制支持使用自定义头部、get和post以外的方法,不一样类型的主题内容。

这种请求已OPTIONS方法发送,下面是它发送的头信息:

Origin

Access-Control-Request-Method 请求自身使用的方法

Access-Control-Request-Headers 自定义头部信息,用逗号分隔

发送请求后,服务器来决定是否容许,服务器会发送以下信息与浏览器沟通:

Access-Control-Allow-Origin 容许的源

Access-Control-Allow-Methods 容许的方法,逗号分隔

Access-Control-Allow-Headers 容许的头部,逗号分隔

Access-Control-Allow-Max-Age Preflight请求缓存的时间(秒)

默认状况下跨域不提供cookie、HTTP认证、SSL证实,经过withCredentials属性设置为true能够指定某个请求因该发送凭据。 服务器若是接收请求会返回Access-Control-Allow-Credentialstrue的头信息。

还有一种方法是使用JSONP

jsonp方法主要是建立script标签来得到数据,通常经过请求后面跟?callback=fn 回掉函数来获取数据。

Fetch

Fetch 是网络请求的一个更好的替代方法。相比于 XMLHttpRequest,Fetch 写法更简单,功能更强大。

fetch('http://a.com')
  .then(function(response) {
    if (response.ok) {
        return response.json();
    }
    throw new Error('err')
  })
  .then(function(myJson) {
    console.log(myJson);
  })
  .catch(err => {
      console.log(err)
  })
复制代码

fetch 函数接受两个参数,返回一个 Promise 对象

第一个参数是 URL 或 Request 对象。第二个参数是可选一个配置项对象。

{
    method: 'GET', // 请求方法
    headers: {
      'user-agent': 'Mozilla/4.0 MDN Example',
      'content-type': 'application/json'
    }, // 头信息
    body: JSON.stringify({data: 1}), // 请求的 body 信息,Blob, FormData 等
    mode: 'cors', // 请求的模式,cors、 no-cors 或 same-origin
    credentials: 'include', // omit、same-origin 或 include。为了在当前域名内自动发送 cookie, 必须提供这个选项
    cache: 'no-cache', // default 、 no-store 、 reload 、 no-cache 、 force-cache 或者 only-if-cached
    redirect: 'follow', // 可用的 redirect 模式: follow (自动重定向), error (若是产生重定向将自动终止而且抛出一个错误), 或者 manual (手动处理重定向).
    referrer: 'no-referrer', // no-referrer、client或一个 URL。默认是 client。
    referrerPolicy: 'no-referrer', // 指定 referer HTTP头
    integrity: 'sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=', // 包括请求的 subresource integrity 值
}
复制代码

then 的回调函数接受一个 Response 对象。Response 实现了 Body(表明响应/请求的正文,容许你声明其内容类型是什么以及应该如何处理。)

它有 9 个属性。

  1. type 只读 包含Response的类型 (例如, basic, cors)
  2. url 只读 包含Response的URL
  3. useFinalURL 包含了一个布尔值来标示这是不是该Response的最终URL
  4. status 只读 包含Response的状态码
  5. ok 只读 包含了一个布尔值来标示该Response成功(状态码200-299)
  6. edirected 只读 表示该Response是否来自一个重定向,若是是的话,它的URL列表将会有多个
  7. statusText 只读 包含了与该Response状态码一致的状态信息
  8. headers 只读 包含此Response所关联的Headers 对象
  9. bodyUsed Body 只读 包含了一个布尔值来标示该Response是否读取过Body

8 个方法

  1. clone 建立一个Response对象的克隆
  2. error 返回一个绑定了网络错误的新的Response对象
  3. redirect(url, status) 用另外一个URL建立一个新的 response

Body(都返回一个 Promise 实例)

  1. arrayBuffer 接受一个 Response 流, 并等待其读取完成. 并 resolve 一个 ArrayBuffer 对象
  2. blob blob()方法使用一个 Response 流,并将其读取完成
  3. formData 将 Response 对象中的所承载的数据流读取并封装成为一个对象
  4. json 使用一个 Response 流,并将其读取完成。解析结果是将文本体解析为 JSON
  5. text 提供了一个可供读取的"返回流", 它返回一个包含USVString对象,编码为UTF-8

WebSocket

WebSockets 是一种先进的技术。它能够在用户的浏览器和服务器之间打开双工、双向通信会话。

WebSocket 构造函数,接受两个参数,url 和 protocols(可选)。

url 以 ws://wss://(加密)开头

protocols 是 单协议字符串或者包含协议字符串的数组。这些字符串用于指定子协议,这样单个服务器能够实现多个WebSocket子协议(例如,您可能但愿一台服务器可以根据指定的协议处理不一样类型的交互)protocol)。若是不指定协议字符串,则假定为空字符串。

var s = new WebSocket('ws://www.a.com/s.php') // 必须传入绝对URL,能够是任何网站
s.readyState // 0 创建链接 1 已经创建 2 正在关闭 3 链接已关闭或者没有连接成功
s.send('hello') // 发送的数据必须是纯文本
s.onopen = function (){
  console.log('成功创建链接时触发')
}
s.onerror = function () {
  console.log('发生错误,链接不能持续时')
}
s.onmessage = function (event) { // 当接收到消息时
  console.log(event.data) // 数据是纯字符
}
s.close() // 关闭链接
s.onclose = function (event) {
  /* * event.wasClean 是否明确的关闭 * event.code 服务器返回的数值状态码 * event.reason 字符串,服务器返回的消息 */
  console.log('链接关闭时')
}
复制代码

一共有 10 个属性

  1. binaryType 返回websocket链接所传输二进制数据的类型(blob, arraybuffer)
  2. bufferedAmount 只读 返回已经被send()方法放入队列中但尚未被发送到网络中的数据的字节数。一旦队列中的全部数据被发送至网络,则该属性值将被重置为0。可是,若在发送过程当中链接被关闭,则属性值不会重置为0。
  3. extensions 只读 返回服务器选择的扩展名。这当前只是空字符串或链接协商的扩展列表
  4. onclose 用于指定链接失败后的回调函数
  5. onmessage 用于指定当从服务器接受到信息时的回调函数
  6. onopen 用于指定链接成功后的回调函数
  7. protocol 只读 服务器选择的下属协议
  8. readyState 只读 当前的连接状态
  9. url 只读 WebSocket 的绝对路径

2 个方法

  1. close(code, reason) 数字状态码 可选 默认 1005和一个可选的类可读的字符串,它解释了链接关闭的缘由。
  2. send(data) 向服务器发送数据(ArrayBuffer,Blob等)
相关文章
相关标签/搜索