摘要:再談異步請求語言將任務的執行模式分成兩種同步和異步。通過對象及時監聽完成事件,執行事件回調函數不會堵塞程序運行。新的是異步請求的另一種方案,比起其復雜糅雜的寫法,能更簡潔的獲取到數據。提供了對和以及其他與網絡請求有關的對象的通用定義。
再談異步請求
Javascript語言將任務的執行模式分成兩種:同步(Synchronous)和異步(Asynchronous)。
在瀏覽器,耗時很長的操作都應該異步執行,避免瀏覽器失去響應,最好的例子就是Ajax操作。通過XHRHttpRequest對象及時監聽完成事件,執行事件回調函數不會堵塞程序運行。
關于FetchFetch API 提供了一個 JavaScript接口,用于訪問和操縱HTTP管道的部分,例如請求和響應。它還提供了一個全局 fetch()方法,該方法提供了一種簡單,合乎邏輯的方式來跨網絡異步獲取資源。這種功能以前是使用 XMLHttpRequest實現的。Fetch提供了一個更好的替代方法,可以很容易地被其他技術使用,例如 Service Workers。Fetch還提供了單個邏輯位置來定義其他HTTP相關概念,例如 CORS和HTTP的擴展。
新的Fetch API是XHRHttpRequest異步請求的另一種方案,比起其復雜糅雜的寫法,fetch能更簡潔的獲取到數據。
XHRHttpRequest使用事件回調函數容易進入回調地獄,而Fetch Api接收url參數返回Promise對象。
Fetch 提供了對 Request 和 Response (以及其他與網絡請求有關的)對象的通用定義。使之今后可以被使用到更多地應用場景中
Fetch的簡單使用let url = "http://jsonplaceholder.typicode.com/users" fetch(url).then((res)=>{ console.log(res) }).catch((err)=>{})
將url傳遞給fetch時會立即返回一個promise對象此時的狀態是pending,當promise被通過時會返回一個response對象。如果我們用習慣了比如jquery封裝好的ajax方法,很容易會以為上面的res就是返回的data。
fetch 只有在遇到網絡錯誤的時候才會 reject 這個 promise,比如用戶斷網或請求地址的域名無法解析等。只要服務器能夠返回 HTTP 響應(甚至只是 CORS preflight 的 OPTIONS 響應),promise 一定是 resolved 的狀態。
fetch返回Promise對象
response.type有以下幾種
basic 標準值,同源響應
cors 收到一個有效的跨域請求
opaque 跨域請求但服務器沒有返回cors響應頭
但是無效的跨域請求如果像下面這么寫,其實根本無法拿到response對象
request.mode用于確定跨域請求是否導致有效的響應
same-origin 同源情況下才可請求成功,否則拋出錯誤
比如在有效的跨域請求設置這個模式會提示
Fetch API cannot load http://jsonplaceholder.typico... Request mode is "same-origin" but the URL"s origin is not same as the request origin file://.
cors: 表示同域和帶有CORS響應頭的跨域下可請求成功.
cors-with-forced-preflight: 表示在發出請求前, 將執行preflight檢查.
no-cors: 用于跨域相應不帶cors的情況,此時相應類型為opaque
根據上面的錯誤修改fetch的模式就可以返回response對象了,可以對比發現無效跨域請求并沒有返回什么有價值的信息例如url,status,statusText等
reponse.body屬于ReadableStream類型
當讀取CSV等大文件時通過流來讀取,可以選擇在讀取到要獲取的數據后停止流,而不是獲取到全部響應數據再去查找。
對于常用返回的幾種數據類型,可以使用blob()、text()、formData()、json(),這幾種方法都會講body標記為已讀數據,所以想再次獲取的時候就會報錯
比如下面的代碼,真實返回的數據不是json類型的,想利用catch方法去捕獲然后再次返回text類型,瀏覽器時會報TypeError: Already read
fetch(url).then(function(response) { return response.json().catch(function() { return response.text(); }); });
正確的方式是使用clone()方法先對數據進行拷貝,響應數據通過clone并不會被回收,一直留在內存中,直至被讀取
fetch(url).then(function(response) { return response.clone().json().catch(function() { return response.text(); }); });Request簡介
method:設置請求方法,默認GET方法
credentials fetch方法默認不發送cookies,如果遇到401 Unauthorized沒有權限問題就要看看是否有設置credentials
omit: 從不發送cookies.
same-origin: 只有當URL與響應腳本同源才發送cookies.
include: 總是發送cookies, 即使來自跨域的請求
默認情況下請求不帶coookie
cache 設置緩存,跟XHR對比在請求時就可以控制緩存,雖然這是有爭議的,因為這暴露了用戶歷史記錄
default
如果是最新的資源,則返回緩存
如果資源已過期則向服務器發出條件請求;如果服務器指示資源沒有改變則返回緩存;否則從服務器中下載,并更新緩存。
如果沒有找到緩存則發出正常情求,但不緩存資源。
no-store 直接從服務器獲取資源并且不會將資源緩存
reload 直接從服務器獲取資源,并且緩存資源
no-cache
如果資源有效或者過期,瀏覽器會發出一個條件請求,如果服務器返回沒有改變,則返回緩存,否則,重新獲取資源并更新緩存
如果不存在資源則瀏覽器發出正常請求下載并更新緩存
force-cache
如果有緩存直接返回緩存,否則下載更新資源
only-if-cached
如果有緩存直接返回緩存,否則瀏覽器返回錯誤
XHR和Fetch其他的對比fetch沒有xhr中的abort()方法來中斷請求
fetch沒有progress進度事件監聽數據,但是你可以通過獲取content-length計算進度
XHR open方法有最后一個參數設為false的時候是同步請求,fetch沒有提供同步請求的方法,但同步請求并不常用
fetch 并沒有像XHR的timeout屬性來設置延時
Fetch實踐體驗習慣了像是vue-resource等插件封裝好的get,post方法,在使用fetch的時候很容易會被它看似簡潔的api給迷惑
fetch兼容性問題
我們需要引入fetch 的polyfill,扒開源碼我們可以發現實現原理還是建立在XMLHttpRequest上的,但是由于polyfill要實現fetch如Blob類文件對象等,在safari和ie上還是有兼容性問題的
參數傳遞問題
在get請求方式中,我們還是只能像xhr那樣以拼接url字符串的方式來傳遞,這與fetch看起來簡潔的api有點不符。
雖然原生的URLSearchParams 接口定義了用來處理 URL 參數串的方法。但是這個api目前兼容性也是不怎么好
var paramsString = "q=URLUtils.searchParams&topic=api"
var searchParams = new URLSearchParams(paramsString);
searchParams.append("topic", "webdev");
searchParams.toString(); // "q=URLUtils.searchParams&topic=api&topic=webdev"
在post請求中,數據要以body字段來傳遞參數,也就是說我們要常用的json格式要經過下面格式的轉換,就像XMLHttpRequest那樣
body 可以是以下任何一種類型的實例:
ArrayBuffer ArrayBufferView (Uint8Array and friends) Blob/File string URLSearchParams FormData
響應數據的問題
在回調函數中我們首先接受到的是response對象,由于body是ReadableStream類型,幾乎很難預先判斷數據是什么類型,也就很難判斷是到底用text()、json()方法解析數據
response對象有一個bodyUsed的屬性初始是false,調用text()、json()等方法會讀取Response對象并且將它設置為已讀,這時bodyUsed為true
bodyUsed初始值為false
- 解決辦法有兩種但都有一定的不足 1.是通過clone加catch方式找到正確的輸出方式,但是要注意調用方法的順序,不然一個json有可能最后還是以text的方式解析,還要注意的是最后要將response的數據回收或者讀取,因為clone方法的讀取并不影響原來的reponse對象
fetch(url).then(function(response) { return response.json().catch(function() { return response.text(); }); });
2.是通過判斷content-type的方式,如果已知的返回格式不多的情況下用還是不錯的選擇
fetch(url).then(function(response) { if (response.headers.get("Content-Type") === "application/json") { return response.json(); } return response.text(); });小結
基于promise的fecth方法可以讓我們遠離回調地獄而不需要其他的封裝。
fetch 將 response.body 設計成 ReadableStream 其實是非常有前瞻性的,這種設計讓你在請求大體積文件時變得非常有用。
參考資料:https://jakearchibald.com/201...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/83899.html
摘要:我們以請求網絡服務為例,來實際測試一下加入多線程之后的效果。所以,執行密集型操作時,多線程是有用的,對于密集型操作,則每次只能使用一個線程。說到這里,對于密集型,可以使用多線程或者多進程來提高效率。 為了提高系統密集型運算的效率,我們常常會使用到多個進程或者是多個線程,python中的Threading包實現了線程,multiprocessing 包則實現了多進程。而在3.2版本的py...
摘要:例子張三刪除用戶為了刪除用戶,我們首先需要定位用戶,然后我們定義方法類型。例子張三結論現在,你已基本了解如何使用的從服務器檢索或操作資源,以及如何處理。您可以使用本文作為如何構建操作的請求的指南。 showImg(https://segmentfault.com/img/bVbjxqh?w=1000&h=562); 本次將介紹如何使用Fetch API(ES6 +)對REST API的...
摘要:簽訂協議的兩方分別是異步接口和。在異步函數中,使用異常捕獲的方案,代替了的異常捕獲的方案。需要注意的是,在異步函數中使異步函數用時要使用,不然異步函會被同步執行。 同步與異步 通常,代碼是由上往下依次執行的。如果有多個任務,就必需排隊,前一個任務完成,后一個任務才會執行。這種執行模式稱之為: 同步(synchronous) 。新手容易把計算機用語中的同步,和日常用語中的同步弄混淆。如,...
摘要:這是我重新復習的原因放棄了之前自己實現的全面擁抱的這個改動是非常大的而且閱讀的源碼可以發現其中大部分函數都支持了類型檢驗和返回值提示值得閱讀 廢話不多說,直接上代碼 __auth__ = aleimu __doc__ = 學習tornado6.0+ 版本與python3.7+ import time import asyncio import tornado.gen import t...
摘要:重構基于的網絡請求庫從屬于筆者的開發基礎與工程實踐系列文章與項目,記述了筆者對內部使用的封裝庫的設計重構與實現過程。基本使用版本中的中,最核心的設計變化在于將請求構建與請求執行剝離了開來。而函數則負責執行請求,并且返回經過擴展的對象。 Fluent Fetcher: 重構基于 Fetch 的 JavaScript 網絡請求庫從屬于筆者的 Web 開發基礎與工程實踐系列文章與項目,記述了...
閱讀 1125·2021-11-24 10:21
閱讀 2561·2021-11-19 11:35
閱讀 1662·2019-08-30 15:55
閱讀 1293·2019-08-30 15:54
閱讀 1192·2019-08-30 15:53
閱讀 3498·2019-08-29 17:21
閱讀 3308·2019-08-29 16:12
閱讀 3412·2019-08-29 15:23