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