另外需要注意的是,若在斷網狀態下調用xhr.send(data)方法,則會拋錯:Uncaught NetworkError: Failed to execute 'send' on 'XMLHttpRequest'。一旦程序拋出錯誤,如果不 catch 就無法繼續執行后面的代碼,所以調用 xhr.send(data)方法時,應該用 try-catch捕捉錯誤。
try{ xhr.send(data) }catch(e){ //doSomething... }; xhr.withCredentials與 CORS 什么關系
我們都知道,在發同域請求時,瀏覽器會將cookie自動加在request header中。但大家是否遇到過這樣的場景:在發送跨域請求時,cookie并沒有自動加在request header中。
造成這個問題的原因是:在CORS標準中做了規定,默認情況下,瀏覽器在發送跨域請求時,不能發送任何認證信息(credentials)如”cookies“和”HTTP authentication schemes“。除非xhr.withCredentials為true(xhr對象有一個屬性叫withCredentials,默認值為false)。
所以根本原因是cookies也是一種認證信息,在跨域請求中,client端必須手動設置xhr.withCredentials=true,且server端也必須允許request能攜帶認證信息(即response header中包含Access-Control-Allow-Credentials:true),這樣瀏覽器才會自動將cookie加在request header中。
另外,要特別注意一點,一旦跨域request能夠攜帶認證信息,server端一定不能將Access-Control-Allow-Origin設置為*,而必須設置為請求頁面的域名。
xhr相關事件 事件分類
xhr相關事件有很多,有時記起來還挺容易混亂。但當我了解了具體代碼實現后,就容易理清楚了。下面是XMLHttpRequest的部分實現代碼:
從代碼中我們可以看出:
XMLHttpRequestEventTarget接口定義了7個事件:
onloadstart
onprogress
onabort
ontimeout
onerror
onload
onloadend
每一個XMLHttpRequest里面都有一個upload屬性,而upload是一個XMLHttpRequestUpload對象
XMLHttpRequest和XMLHttpRequestUpload都繼承了同一個XMLHttpRequestEventTarget接口,所以xhr和xhr.upload都有第一條列舉的7個事件
onreadystatechange是XMLHttpRequest獨有的事件
所以這么一看就很清晰了:
xhr一共有8個相關事件:7個XMLHttpRequestEventTarget事件+1個獨有的onreadystatechange事件;而xhr.upload只有7個XMLHttpRequestEventTarget事件。
事件觸發條件
下面是我自己整理的一張xhr相關事件觸發條件表,其中最需要注意的是 onerror 事件的觸發條件。
事件 觸發條件
當請求一切正常時,相關的事件觸發順序如下:
觸發xhr.onreadystatechange(之后每次readyState變化時,都會觸發一次)
觸發xhr.onloadstart
//上傳階段開始:
觸發xhr.upload.onloadstart
觸發xhr.upload.onprogress
觸發xhr.upload.onload
觸發xhr.upload.onloadend
//上傳結束,下載階段開始:
觸發xhr.onprogress
觸發xhr.onload
觸發xhr.onloadend
發生abort/timeout/error異常的處理
在請求的過程中,有可能發生 abort/timeout/error這3種異常。那么一旦發生這些異常,xhr后續會進行哪些處理呢?后續處理如下:
一旦發生abort或timeout或error異常,先立即中止當前請求
將 readystate 置為4,并觸發 xhr.onreadystatechange事件
如果上傳階段還沒有結束,則依次觸發以下事件:
xhr.upload.onprogress
xhr.upload.[onabort或ontimeout或onerror]
xhr.upload.onloadend
觸發 xhr.onprogress事件
觸發 xhr.[onabort或ontimeout或onerror]事件
觸發xhr.onloadend 事件
在哪個xhr事件中注冊成功回調?
評論