請求 - Fetch(未完)


概念和用法

  • 可以被使用到更多地應用場景中:無論是service workers、Cache API、又或者是其他處理請求和響應的方式,甚至是任何一種需要你自己在程序中生成響應的方式。
    • Cache 接口為緩存的 Request / Response 對象對提供存儲機制
  • 為有關聯性的概念,例如CORS和HTTP原生頭信息,提供一種新的定義,取代它們原來那種分離的定義。
  • 在Window 和 WorkerGlobalScope接口上實現了這個方法。因此在幾乎所有環境中都可以用這個方法獲取到資源。
    • WorkerGlobalScope 接口 是一個代表了任何 scope of worker的接口(屬於worker的對象)
  • 無論請求成功與否,它都返回一個 Promise 對象
  • 可以通過 Request() 和 Response() 的構造函數直接創建請求和響應,但是我們不建議這么做。他們應該被用於創建其他 API 的結果(比如,service workers 中的 FetchEvent.respondWith)。
    • 使用ServiceWorker技術時,頁面的提取動作會在ServiceWorker作用域(ServiceWorkerGlobalScope)中觸發fetch事件.(應該是請求動作)
    • 使用ServiceWorkerGlobalScope.onfetch或addEventListener監聽.該事件回調會注入FetchEvent參數.它攜帶了有關請求和結果響應的信息以及方法
    • FetchEvent.respondWith() ,允許我們向受控頁面提供任意響應.

中止 fetch

  • 瀏覽器已經開始為AbortController 和AbortSignal 接口(也就是Abort API)添加實驗性支持,允許像 Fetch 和 XHR 這樣的操作在還未完成時被中止 。

————————————————————————————————————————

AbortController

  • AbortController接口代表一個控制器對象,允許你在需要時中止一個或多個DOM請求。
  • 使用AbortController.AbortController()構造函數創建一個新的AbortController對象。
  • 使用AbortSignal 對象完成與DOM請求的通信。

構造函數

  • AbortController.AbortController() 創建一個新的AbortController 對象實例。

屬性

  • AbortController.signal 返回一個AbortSignal對象實例,它可以用來 with/abort(具有/終止) 一個DOM請求。

方法

  • AbortController.abort() 中止一個尚未完成的DOM請求。這能夠中止fetch 請求,任何響應Body的消費者和流。
    • 當abort() 被調用,fetch() promise rejects 一個 AbortError。

示例

var controller = new AbortController(); // 創建一個控制器
var signal = controller.signal; // 獲取該控制得信號對象

var downloadBtn = document.querySelector('.download');
var abortBtn = document.querySelector('.abort');

downloadBtn.addEventListener('click', fetchVideo);

abortBtn.addEventListener('click', function() {
  controller.abort(); // 通過控制器終止它得信號對象關聯得一個或多個請求
  console.log('Download aborted');
});

function fetchVideo() {
  ...
  fetch(url, {signal}).then(function(response) { // fetch方法參數2多了一個選項signal,用來把信號對象綁定到對應得請求中去,才能實現控制器得控制
    ...
  }).catch(function(e) {
    reports.textContent = 'Download error: ' + e.message;
  })
}

————————————————————————————————————————

AbortSignal

  • AbortSignal 接口表示一個信號對象( signal object ),它允許您通過 AbortController 對象與DOM請求(如Fetch)進行通信並在需要時將其中止。(實際是AbortController通過它和請求關聯,關聯得請求才能被控制器操作)

屬性

  • AbortSignal接口還繼承了其父接口EventTarget的屬性。
    • EventTarget是一個由可以接收事件的對象實現的接口,並且可以為它們創建偵聽器。(一個類,具有addEventListener等和事件相關得方法)
  • AbortSignal.aborted (只讀)以 Boolean 表示與之通信的請求是否被終止(true)或未終止(false)。

事件處理

  • AbortSignal.onabort 當 abort 事件觸發時,即當信號正在與之通信的DOM請求被中止時調用。

方法

  • AbortSignal接口從其父接口 EventTarget 繼承方法。

————————————————————————————————————————

Fetch

  • 位於 WorkerOrGlobalScope 這一個 mixin 中的 fetch() 方法用於發起獲取資源的請求。它返回一個 promise,這個 promise 會在請求響應后被 resolve,並傳回 Response 對象。
    • Response 對象:作為參數傳入then函數中的回調函數
  • Window 和 WorkerGlobalScope 都實現了 WorkerOrGlobalScope。 ——這意味着基本在任何場景下只要你想獲取資源,都可以使用 位於 WorkerOrGlobalScope 中的 fetch() 方法。
  • 當遇到網絡錯誤時,fetch() 返回的 promise 會被 reject,並傳回 TypeError(HTTP 404 狀態並不被認為是網絡錯誤。)
  • fetch() 方法由 Content Security Policy 的 connect-src指令控制,而不是它請求的資源。
    • Content Security Policy:HTTP 響應頭允許站點管理者控制用戶代理能夠為指定的頁面加載哪些資源。將幫助防止跨站腳本攻擊(Cross-Site Script)(XSS)
    • connect-src:限制能通過腳本接口加載的URL。

語法

Promise<Response> fetch(input[, init]);

參數

  • input 定義要獲取的資源。這可能是:
    • 一個 USVString 字符串,包含要獲取資源的 URL。
      • USVString 對應 unicode 標量值的所有可能序列的集合。它通常僅用於執行文本處理的 API,需要一串 unicode 標量值才能進行操作。除了不允許不成對的代理代碼(應該是代理碼點)之外, USVString 等同於 DOMString 。
      • DOMString 是一個UTF-16字符串。由於JavaScript已經使用了這樣的字符串,所以DOMString 直接映射到 一個String。
    • 一個 Request 對象
  • init 一個配置項對象,包括所有對請求的設置。可選的參數有:
    • method: 請求使用的方法,如 GET、POST。
    • headers: 請求的頭信息,形式為 Headers 的對象或包含 ByteString 值的對象字面量。
      • ByteString is a UTF-8 String that corresponds to the set of all possible sequences of bytes. (bytestring是一個utf-8字符串,它對應於所有可能的字節序列集。)
    • body: 請求的 body 信息:可能是一個 Blob、BufferSource、FormData、URLSearchParams 或者 USVString 對象。注意 GET 或 HEAD 方法的請求不能包含 body 信息。
      • BufferSource 一個類型,包括ArrayBuffer和ArrayBufferView.
      • ArrayBuffer 對象用來表示通用的、固定長度的原始二進制數據緩沖區。
      • ArrayBufferView is a helper type representing any of the following JavaScript TypedArray types(多種類數組二進制數據類型)
    • mode: 請求的模式,如 cors、 no-cors 或者 same-origin。
      • cors:
      • no-cors:
      • same-origin:
    • credentials: 請求的 credentials,如 omit、same-origin 或者 include。
      • omit:確保瀏覽器不在請求中包含憑據
      • same-origin:請求URL與調用腳本位於同一起源處時發送憑據
      • include:讓瀏覽器發送包含憑據的請求(即使是跨域源)
    • cache: 請求的 cache 模式: default 、 no-store 、 reload 、 no-cache 、 force-cache 或者 only-if-cached 。
      • default:
      • no-store:緩存不應存儲有關客戶端請求或服務器響應的任何內容?來源於瀏覽器緩存
      • reload:
      • no-cache:強制高速緩存將請求提交給原始服務器進行驗證。?來源於瀏覽器緩存
      • force-cache:
      • only-if-cached:表明客戶端只接受已緩存的響應,並且不要向原始服務器檢查是否有更新的拷貝?來源於瀏覽器緩存
    • redirect: 可用的 redirect 模式: follow (自動重定向), error (如果產生重定向將自動終止並且拋出一個錯誤), 或者 manual (手動處理重定向,默認值).
      • 當響應為重定向時的動作
    • referrer: 一個 USVString 可以是 no-referrer、client或一個 URL。默認是 client。
      • no-referrer:表示 Referer: 頭將不會被發送。來源於跳轉方法
      • client:
      • 一個 URL:
    • referrerPolicy: 指定HTTP頭 referer 的值 no-referrer、 no-referrer-when-downgrade、 origin、 origin-when-cross-origin、 unsafe-url (和referrer有什么區別?)
      • no-referrer:
      • no-referrer-when-downgrade:表示當從使用HTTPS的頁面導航到非 HTTPS 頁面時不會發送 Referer: 頭。來源於跳轉方法
      • origin:
      • origin-when-cross-origin:表示導航到其它源將會限制為這種組合:主機 + 端口,而導航到相同的源將會只包含 referrer的路徑。來源於跳轉方法
      • unsafe-url:表示 referrer將會包含源和路徑(domain + path)(但是不包含密碼或用戶名的片段)。這種情況是不安全的,因為它可能會將安全的URLs數據泄露給不安全的源。來源於跳轉方法
    • integrity: 包括請求的 subresource integrity 值 ( 例如: sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=)。
      • subresource integrity 資源的哈希編碼,用於校驗資源的完整性

返回值

  • 一個 Promise,resolve 時回傳 Response 對象。

例外(錯誤類型)

  • AbortError:The request was aborted (using AbortController.abort()).(請求被終止,使用了 AbortController.abort())
  • TypeError:Since Firefox 43, fetch() will throw a TypeError if the URL has credentials, such as http://user:password@example.com.(傳入的URL包含憑據時拋出,例如 http://user:password@example.com

示例

  • 把圖片2進制對象轉換為URL地址,供帶有src屬性的標簽使用。
var myImage = document.querySelector('img');

var myRequest = new Request('flowers.jpg');

fetch(myRequest).then(function(response) {
  return response.blob();
}).then(function(response) {
  var objectURL = URL.createObjectURL(response); // `objectURL = blob:https://www.w3cschool.cn/93496b0c-601c-4675-8a25-c64df2d662df`
  myImage.src = objectURL;
});

————————————————————————————————————————

Headers

  • Headers 接口允許您對HTTP請求和響應頭執行各種操作。
  • 在該接口的所有方法中,標題名稱由不區分大小寫的字節序列匹配。?
  • 出於安全考慮,某些頭只能由用戶代理控制。這些頭信息包括
    • 請求首部
      • 禁止修改的消息首部包括以 Proxy- 和 Sec- 開頭的消息首部,
      • Accept-Charset:用來告知(服務器)客戶端可以處理的字符集類型。Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
      • Accept-Encoding:客戶端能夠理解的內容編碼方式——通常是某種壓縮算法——進行通知Accept-Encoding: gzip,deflate
      • Access-Control-Request-Headers:告知服務器,實際請求將攜帶的自定義請求首部字段Access-Control-Request-Headers: X-PINGOTHER
      • Access-Control-Request-Method:告知服務器,實際請求將使用的請求方法
      • Connection:決定當前的事務完成后,是否會關閉網絡連接。如果該值是“keep-alive”,網絡連接就是持久的,不會關閉,使得對同一個服務器的請求可以繼續在該連接上完成。
      • Content-Length:一個實體消息首部,用來指明發送給接收方的消息主體的大小,即用十進制數字表示的八位元組的數目。
      • Cookie
      • Cookie2(已廢棄)
      • Date
      • DNT:表明了用戶對於網站追蹤的偏好。
      • Expect:一個請求消息頭,包含一個期望條件,表示服務器只有在滿足此期望條件的情況下才能妥善地處理請求。
        • 規范中只規定了一個期望條件Expect: 100-continue通知接收方客戶端要發送一個體積可能很大的消息體,期望收到狀態碼為100(代表能夠處理)否則返回417(節省流量)
      • Host:請求頭指明了服務器的域名(對於虛擬主機來說),以及(可選的)服務器監聽的TCP端口號。
      • Keep-Alive:一個通用消息頭,允許消息發送者暗示連接的狀態,還可以用來設置超時時長和最大請求數。(最大請求數:一次鏈接可以包含多個請求)
      • Origin:指示了請求來自於哪個站點。該字段僅指示服務器名稱,並不包含任何路徑信息
      • Referer:包含了當前請求頁面的來源頁面的地址,即表示當前頁面是通過此來源頁面里的鏈接進入的。
      • TE:請求型頭部用來指定用戶代理希望使用的傳輸編碼類型。TE: gzip
      • Trailer:一個響應首部,允許發送方在分塊發送的消息后面添加額外的元信息,這些元信息可能是隨着消息主體的發送動態生成的,比如消息的完整性校驗,消息的數字簽名,或者消息經過處理之后的最終狀態等。(實體的元信息?)
      • Transfer-Encoding: 消息首部指明了將 entity(實體) 安全傳遞給用戶所采用的編碼形式。Transfer-Encoding: gzip(實體的編碼方式?)
      • Upgrade:客戶機指定它支持哪些額外的通信協議,如果服務器發現它適合於切換協議(非MDN)
      • Via:一個通用首部,是由代理服務器添加的,適用於正向和反向代理,在請求和響應首部中均可出現。這個消息首部可以用來追蹤消息轉發情況,防止循環請求,以及識別在請求或響應傳遞鏈中消息發送者對於協議的支持能力。?
    • 響應頭部
      • Set-Cookie
      • Set-Cookie2
  • 一個Headers對象都有一個關聯的guard,它具有不可變的值,request,request-no-cors,response或none。 這會影響 set(), delete(), 和append() 方法 改變header.
    • 當使用 Headers() constructor 創建一個新的 Headers 對象的時候,它的 guard 被設置成 none(默認值)。
    • 當創建 Request 或 Response 對象的時候,它將擁有一個按照以下規則實現的與之關聯的 Headers 對象。
      • Request() 構造函數 guard 為 request
      • Request() 構造函數 mode 設置成 no-cors 時 guard 為 request-no-cors
      • Response() 構造函數 guard 為 response
      • Response.error()/Response.redirect() guard 為 immutable
    • Guard 是 Headers 對象的特性,基於不同的情況,它可以有以下取值:immutable、request、request-no-cors、response 或 none。
      • none:可以修改(不包括禁止的首部)
      • request:請求頭部,可以修改(不包括禁止的首部)
      • request-no-cors:請求頭部,只允許修改簡單請求包括的頭部(簡單請求的頭部和可人為修改的 CORS 安全首部相同,參考https://www.cnblogs.com/qq3279338858/p/11053015.html)
      • response:響應頭部,可以修改(不包括禁止的首部)
      • immutable:不允許修改Headers
  • 可以通過 Request.headers 和 Response.headers 屬性檢索一個Headers對象
  • 使用 Headers.Headers() 構造函數創建一個新的Headers 對象
  • 一個實現了Headers 的對象可以直接用於 for...of 結構中, 而不是 entries(): for (var p of myHeaders) 等價於 for (var p of myHeaders.entries()).
    • Object對象沒有Symbol.iterator方法,即沒有內置迭代器,所以不支持for of循環
  • 如果您嘗試傳入名稱不是有效的HTTP頭名稱的引用,則所有Headers方法都將引發 TypeError

構造函數

  • Headers.Headers() 創建一個新的Headers對象.

方法

  • Headers.append() 給現有的header添加一個值, 或者添加一個未存在的header並賦值.(新增)
  • Headers.delete() 從Headers對象中刪除指定header.
  • Headers.entries() 以 迭代器 的形式返回Headers對象中所有的鍵值對.
  • Headers.get() 以 ByteString 的形式從Headers對象中返回指定header的全部值.
    • ByteString 是一個可以對應所有可能的字節序列的字符串。在JavaScript中,當返回時ByteString映射到一個 String ; 通常,它只被用與協議交互式進行字節和字符串的相互轉換 ,例如HTTP協議。?
  • Headers.has() 以布爾值的形式從Headers對象中返回是否存在指定的header.
  • Headers.keys() 以迭代器的形式返回Headers對象中所有存在的header名.
  • Headers.set() 替換現有的header的值, 或者添加一個未存在的header並賦值.(替換)
  • Headers.values() 以迭代器的形式返回Headers對象中所有存在的header的值.

范例

let myHeaders = new Headers();

myHeaders.append('Content-Type', 'text/xml');

myHeaders.get('Content-Type');
// should return 'text/xml'

————————————————————————————————————————

Body

  • Body mixin(類) 代表響應/請求的正文,允許你聲明其內容類型是什么以及應該如何處理。
  • Body被Request 和Response實現,並為這些對象提供了
    • 一個相關聯的主體(字節流)
    • 一個已使用的標志(最初未設置)
    • 一個MIME類型(最初為空字節序列)。

屬性(只讀)

  • Body.body 一個簡單的getter用於暴露一個ReadableStream類型的主體內容。
  • Body.bodyUsed 一個Boolean 值指示是否body已經被標記讀取。

方法

  • Body.arrayBuffer() 使Response掛起一個流操作並且在完成時讀取其值,它返回一個Promise對象,其resolve參數類型是ArrayBuffer。此操作會將bodyUsed狀態改為已使用(true)。
    • ArrayBuffer 對象用來表示通用的、固定長度的原始二進制數據緩沖區。
  • Body.blob() 使Response掛起一個流操作並且在完成時讀取其值,它返回一個Promise對象,其resolve參數類型是Blob。此操作會將bodyUsed狀態改為已使用(true)。
  • Body.formData() 使Response掛起一個流操作並且在完成時讀取其值,它返回一個Promise對象,其resolve參數類型是FormData表單。此操作會將bodyUsed狀態改為已使用(true)。
  • Body.json() 使Response掛起一個流操作並且在完成時讀取其值,它返回一個Promise對象,其resolve參數類型是使用JSON解析body文本的結果。此操作會將bodyUsed狀態改為已使用(true)。
  • Body.text() 使Response掛起一個流操作並且在完成時讀取其值,它返回一個Promise對象,其resolve參數類型是USVString(文本)。此操作會將bodyUsed狀態改為已使用(true)。

范例

  • 使用 Response.Response() 構造函數創建自定義的 Response 對象。
const response = new Response();

————————————————————————————————————————

ReadableStream

  • 流操作API中的ReadableStream 接口呈現了一個可讀取的二進制流操作。
    • 流將你希望通過網絡接收的資源拆分成小塊,然后按位處理它。這正是瀏覽器在接收用於顯示web頁面的資源時做的事情——視頻緩沖區和更多的內容可以逐漸播放,有時候隨着內容的加載,你可以看到圖像逐漸地顯示。
    • 但曾經這些對於JavaScript是不可用的。以前,如果我們想要處理某種資源(如視頻、文本文件等),我們必須下載完整的文件,等待它反序列化成適當的格式,然后在完整地接收到所有的內容后再進行處理

構造函數

  • ReadableStream() 創建並從給定的Handler(處理程序)返回一個可讀流對象。

屬性

  • ReadableStream.locked locked返回這個可讀流是否被一個讀取器鎖定。

方法

  • ReadableStream.cancel() 取消讀取一束流, 消耗方發出一個信號,表示對這束流失去興趣. 可以提供一個參數表示其原因給到底層代碼, 使得不在應用這束流。(解鎖?)
  • ReadableStream.getReader() 創建一個讀取器並且鎖定流到讀取器上,其他的讀取器不能再捕獲它,直到它被釋放。
  • ReadableStream.pipeThrough() 提供一個鏈式方法用於管道化一個現有的流,通過一個變換流或其他的可寫可讀對。?
  • ReadableStream.pipeTo() 將現有的可讀流管道輸出給一個給定的可寫流WritableStream,並在輸出成功時保證填充,或在發生錯誤時返回拒絕。
  • ReadableStream.tee() 返回包含兩個ReadableStream實例分支的數組,每個元素接收了相同的傳輸數據

使用例程

  • fetch一個請求並不是立馬返回請求的結果,而是返回這個請求已經被成功響應,需要的結果正在傳輸過程中。所以上文提到Body的方法都返回一個Promise對象,就是用來等待結果數據完全傳輸后進行處理,切換Promise狀態。?
fetch("https://www.example.org/").then((response) => {
  const reader = response.body.getReader();
  const stream = new ReadableStream({
    start(controller) {
      // 下面的函數處理每個數據塊
      function push() {
        // "done"是一個布爾型,"value"是一個Unit8Array
        reader.read().then(({ done, value }) => {
          // 判斷是否還有可讀的數據?
          if (done) {
            // 告訴瀏覽器已經結束數據發送。
            controller.close();
            return;
          }
          // 取得數據並將它通過controller發送給瀏覽器。
          controller.enqueue(value);
          push();
        });
      };      
      push();
    }
  });

  return new Response(stream, { headers: { "Content-Type": "text/html" } });
});

————————————————————————————————————————

Request(請求)

  • 可以使用 Request.Request() 構造函數創建一個Request 對象
  • 可能會遇到一個 Request 對象作為其它 API 的操作返回,比如 service worker 的FetchEvent.request。

構造器

  • Request.Request() 創建一個新的 Request 對象。
    • 傳參可能和Fetch相同?

屬性(只讀)

  • Request.method 包含請求的方法 (GET, POST, 等.)
  • Request.url 包含這個請求的URL
  • Request.headers 包含請求相關的Headers對象。
  • Request.referrer 包含請求的來源 (例如:client)。
  • Request.referrerPolicy 包含請求來源的策略 (例如:no-referrer)。
  • Request.mode 包含請求的模式 (例如: cors, no-cors, same-origin, navigate).
  • Request.credentials 包含請求的證書(例如: omit, same-origin).
  • Request.redirect 包含如何處理重定向模式,它可能是一個 follow ,error或者manual。
  • Request.integrity 包含請求的子資源的完整性值 (例如: sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=).
  • Request.cache 包含請求的緩存模式 (例如: default, reload, no-cache).
  • Request實現了Body, 所以它還具有以下屬性可用:
    • Body.body 一個簡單getter用於曝光一個ReadableStream的主體內容.
    • Body.bodyUsed 存儲一個Boolean判斷主體是否已經被用於一個響應中.

方法

  • Request.clone() 創建當前request的副本。
  • Request實現 Body, 因此它也有以下方法可用:(這些Body功能只能運行一次; 隨后的調用將通過空strings/ ArrayBuffers解析.)
    • Body.arrayBuffer() 返回解決一個ArrayBuffer表示的請求主體的promise.
    • Body.blob()
    • Body.formData()
    • Body.json()
    • Body.text()

示例

  • 通過將Request對象作為參數傳遞給GlobalFetch.fetch()調用來獲取此請求
const myRequest = new Request('http://localhost/flowers.jpg');

fetch(myRequest)
  .then(response => response.blob())
  .then(blob => {
    myImage.src = URL.createObjectURL(blob);
  });

————————————————————————————————————————

Response(響應)

  • Response 接口呈現了對一次請求的響應數據
  • 可以使用Response.Response() 構造函數來創建一個 Response 對象
  • 其他的API操作返回了一個Response對象,例如一個service worker 的Fetchevent.respondWith,或者一個簡單的 GlobalFetch.fetch()

構造函數

  • Response.Response() 創建一個新的Response 對象.

屬性(大部分只讀)

  • Response.headers 包含此Response所關聯的Headers 對象.
  • Response.ok 包含了一個布爾值來標示該 Response 成功(狀態碼的范圍在200-299)
  • Response.redirected 表示該Response是否來自一個重定向,如果是的話,它的URL列表將會有多個entry
  • Response.status 包含Response的狀態碼 (例如 200 表示成功)
  • Response.statusText 包含了與該Response狀態碼一致的狀態信息 (例如, OK對應 200).
  • Response.type 包含Response的類型 (例如, basic, cors).
    • basic: 標准值, 同源響應, 帶有所有的頭部信息除了“Set-Cookie” 和 “Set-Cookie2″.
    • cors: Response 接收到一個有效的跨域請求. 部分headers和body可以被訪問.
    • error: 網絡錯誤. 沒有有用的描述錯誤的信息。響應的狀態為0,header為空且不可變。從 Response.error()中獲得的響應的類型.
    • opaque: 響應 “no-cors” 的跨域請求. 嚴重受限.
  • Response.url 包含Response的URL.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM