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