XMLHttpRequest æ¯ä¸ä¸ªå
å»ºçæµè§å¨å¯¹è±¡ï¼å®å
è®¸ä½¿ç¨ JavaScript åé HTTP 请æ±ã
è½ç¶å®çååé颿 âXMLâ ä¸è¯ï¼ä½å®å¯ä»¥æä½ä»»ä½æ°æ®ï¼èä¸ä» ä» æ¯ XML æ ¼å¼ãæä»¬å¯ä»¥ç¨å®æ¥ä¸ä¼ /ä¸è½½æä»¶ï¼è·è¸ªè¿åº¦çã
ç°å¦ä»ï¼æä»¬æä¸ä¸ªæ´ä¸ºç°ä»£çæ¹æ³å«å fetchï¼å®çåºç°ä½¿å¾ XMLHttpRequest 卿ç§ç¨åº¦ä¸è¢«å¼ç¨ã
å¨ç°ä»£ Web å¼åä¸ï¼åºäºä»¥ä¸ä¸ç§åå ï¼æä»¬è¿å¨ä½¿ç¨ XMLHttpRequestï¼
- åå²åå ï¼æä»¬éè¦æ¯æç°æç使ç¨äº
XMLHttpRequestçèæ¬ã - æä»¬éè¦å ¼å®¹æ§æµè§å¨ï¼å¹¶ä¸ä¸æ³ç¨ polyfillï¼ä¾å¦ä¸ºäºä½¿èæ¬æ´å°ï¼ã
- æä»¬éè¦åä¸äº
fetchç®åæ æ³åå°çäºæ ï¼ä¾å¦è·è¸ªä¸ä¼ è¿åº¦ã
è¿äºè¯å¬èµ·æ¥çæåï¼å¦ææ¯ï¼é£ä¹è¯·ç»§ç»é
读ä¸é¢ç XMLHttpRequest ç¸å
³å
容å§ã妿è¿ä¸æ¯å¾çæçè¯ï¼é£ä¹è¯·å
é
读 Fetch ä¸ç« çå
容ã
XMLHttpRequest åºç¡
XMLHttpRequest æä¸¤ç§æ§è¡æ¨¡å¼ï¼åæ¥ï¼synchronousï¼å弿¥ï¼asynchronousï¼ã
æä»¬é¦å æ¥ççæå¸¸ç¨ç弿¥æ¨¡å¼ï¼
è¦åé请æ±ï¼éè¦ 3 个æ¥éª¤ï¼
-
å建
XMLHttpRequestï¼let xhr = new XMLHttpRequest();æ¤æé 卿²¡æåæ°ã
-
åå§åå®ï¼é常就å¨
new XMLHttpRequestä¹åï¼xhr.open(method, URL, [async, user, password])æ¤æ¹æ³æå®è¯·æ±ç主è¦åæ°ï¼
methodââ HTTP æ¹æ³ãé常æ¯"GET"æ"POST"ãURLââ è¦è¯·æ±ç URLï¼é常æ¯ä¸ä¸ªå符串ï¼ä¹å¯ä»¥æ¯ URL 对象ãasyncââ 妿æ¾å¼å°è®¾ç½®ä¸ºfalseï¼é£ä¹è¯·æ±å°ä¼ä»¥åæ¥çæ¹å¼å¤çï¼æä»¬ç¨åä¼è®²å°å®ãuserï¼passwordââ HTTP åºæ¬èº«ä»½éªè¯ï¼å¦æéè¦çè¯ï¼çç»å½ååå¯ç ã
请注æï¼
openè°ç¨ä¸å ¶åç§°ç¸åï¼ä¸ä¼å»ºç«è¿æ¥ãå®ä» é 置请æ±ï¼èç½ç»æ´»å¨ä» 以sendè°ç¨å¼å¯ã -
åé请æ±ã
xhr.send([body])è¿ä¸ªæ¹æ³ä¼å»ºç«è¿æ¥ï¼å¹¶å°è¯·æ±åéå°æå¡å¨ãå¯éåæ°
bodyå å«äº request bodyãä¸äºè¯·æ±æ¹æ³ï¼å
GET没æ request bodyãè¿æä¸äºè¯·æ±æ¹æ³ï¼åPOST使ç¨bodyå°æ°æ®åéå°æå¡å¨ãæä»¬ç¨åä¼çå°ç¸åºç¤ºä¾ã -
çå¬
xhräºä»¶ä»¥è·åååºãè¿ä¸ä¸ªäºä»¶æ¯æå¸¸ç¨çï¼
loadââ å½è¯·æ±å®æï¼å³ä½¿ HTTP ç¶æä¸º 400 æ 500 çï¼ï¼å¹¶ä¸ååºå·²å®å ¨ä¸è½½ãerrorââ 彿 æ³ååºè¯·æ±ï¼ä¾å¦ç½ç»ä¸ææè æ æç URLãprogressââ å¨ä¸è½½ååºæé´å®æè§¦åï¼æ¥åå·²ç»ä¸è½½äºå¤å°ã
xhr.onload = function() { alert(`Loaded: ${xhr.status} ${xhr.response}`); }; xhr.onerror = function() { // ä» å¨æ ¹æ¬æ æ³ååºè¯·æ±æ¶è§¦å alert(`Network Error`); }; xhr.onprogress = function(event) { // å®æè§¦å // event.loaded ââ å·²ç»ä¸è½½äºå¤å°åè // event.lengthComputable = trueï¼å½æå¡å¨åéäº Content-Length header æ¶ // event.total ââ æ»åèæ°ï¼å¦æ lengthComputable 为 trueï¼ alert(`Received ${event.loaded} of ${event.total}`); };
ä¸é¢æ¯ä¸ä¸ªå®æ´ç示ä¾ãå®ä»æå¡å¨å è½½ /article/xmlhttprequest/example/loadï¼å¹¶æå°å è½½è¿åº¦ï¼
// 1. å建ä¸ä¸ª new XMLHttpRequest 对象
let xhr = new XMLHttpRequest();
// 2. é
ç½®å®ï¼ä» URL /article/.../load GET-request
xhr.open('GET', '/article/xmlhttprequest/example/load');
// 3. éè¿ç½ç»åé请æ±
xhr.send();
// 4. 彿¥æ¶å°ååºåï¼å°è°ç¨æ¤å½æ°
xhr.onload = function() {
if (xhr.status != 200) { // åæååºç HTTP ç¶æ
alert(`Error ${xhr.status}: ${xhr.statusText}`); // ä¾å¦ 404: Not Found
} else { // æ¾ç¤ºç»æ
alert(`Done, got ${xhr.response.length} bytes`); // response æ¯æå¡å¨ååº
}
};
xhr.onprogress = function(event) {
if (event.lengthComputable) {
alert(`Received ${event.loaded} of ${event.total} bytes`);
} else {
alert(`Received ${event.loaded} bytes`); // 没æ Content-Length
}
};
xhr.onerror = function() {
alert("Request failed");
};
䏿¦æå¡å¨æäºååºï¼æä»¬å¯ä»¥å¨ä»¥ä¸ xhr 屿§ä¸æ¥æ¶ç»æï¼
status- HTTP ç¶æç ï¼ä¸ä¸ªæ°åï¼ï¼
200ï¼404ï¼403çï¼å¦æåºç°é HTTP é误ï¼å为0ã statusText- HTTP ç¶ææ¶æ¯ï¼ä¸ä¸ªå符串ï¼ï¼ç¶æç 为
200对åºäºOKï¼404对åºäºNot Foundï¼403对åºäºForbiddenã responseï¼æ§èæ¬å¯è½ç¨çæ¯responseTextï¼- æå¡å¨ response bodyã
æä»¬è¿å¯ä»¥ä½¿ç¨ç¸åºç屿§æå®è¶ æ¶ï¼timeoutï¼ï¼
xhr.timeout = 10000; // timeout å使¯ msï¼æ¤å¤å³ 10 ç§
妿å¨ç»å®æ¶é´å
è¯·æ±æ²¡ææåæ§è¡ï¼è¯·æ±å°±ä¼è¢«åæ¶ï¼å¹¶ä¸è§¦å timeout äºä»¶ã
为äºå URL æ·»å å ?name=value è¿æ ·çåæ°ï¼å¹¶ç¡®ä¿æ£ç¡®çç¼ç ï¼æä»¬å¯ä»¥ä½¿ç¨ URL 对象ï¼
let url = new URL('https://google.com/search');
url.searchParams.set('q', 'test me!');
// åæ° 'q' 被ç¼ç
xhr.open('GET', url); // https://google.com/search?q=test+me%21
ååºç±»å
æä»¬å¯ä»¥ä½¿ç¨ xhr.responseType 屿§æ¥è®¾ç½®ååºæ ¼å¼ï¼
""ï¼é»è®¤ï¼ââ ååºæ ¼å¼ä¸ºå符串ï¼"text"ââ ååºæ ¼å¼ä¸ºå符串ï¼"arraybuffer"ââ ååºæ ¼å¼ä¸ºArrayBufferï¼å¯¹äºäºè¿å¶æ°æ®ï¼è¯·åè§ ArrayBufferï¼äºè¿å¶æ°ç»ï¼ï¼"blob"ââ ååºæ ¼å¼ä¸ºBlobï¼å¯¹äºäºè¿å¶æ°æ®ï¼è¯·åè§ Blobï¼ï¼"document"ââ ååºæ ¼å¼ä¸º XML documentï¼å¯ä»¥ä½¿ç¨ XPath åå ¶ä» XML æ¹æ³ï¼æ HTML documentï¼åºäºæ¥æ¶æ°æ®ç MIME ç±»åï¼"json"ââ ååºæ ¼å¼ä¸º JSONï¼èªå¨è§£æï¼ã
ä¾å¦ï¼æä»¬ä»¥ JSON æ ¼å¼è·åååºï¼
let xhr = new XMLHttpRequest();
xhr.open('GET', '/article/xmlhttprequest/example/json');
xhr.responseType = 'json';
xhr.send();
// ååºä¸º {"message": "Hello, world!"}
xhr.onload = function() {
let responseObj = xhr.response;
alert(responseObj.message); // Hello, world!
};
卿§çèæ¬ä¸ï¼ä½ å¯è½ä¼çå° xhr.responseTextï¼çè³ä¼çå° xhr.responseXML 屿§ã
å®ä»¬æ¯ç±äºåå²åå èåå¨çï¼ä»¥è·åå符串æ XML ææ¡£ãå¦ä»ï¼æä»¬åºè¯¥å¨ xhr.responseType ä¸è®¾ç½®æ ¼å¼ï¼ç¶åå°±è½è·åå¦ä¸æç¤ºç xhr.response äºã
readyState
XMLHttpRequest çç¶æï¼stateï¼ä¼éçå®çå¤çè¿åº¦ååèååãå¯ä»¥éè¿ xhr.readyState æ¥äºè§£å½åç¶æã
è§è 䏿å°çææç¶æå¦ä¸ï¼
UNSENT = 0; // åå§ç¶æ
OPENED = 1; // open 被è°ç¨
HEADERS_RECEIVED = 2; // æ¥æ¶å° response header
LOADING = 3; // ååºæ£å¨è¢«å è½½ï¼æ¥æ¶å°ä¸ä¸ªæ°æ®å
ï¼
DONE = 4; // 请æ±å®æ
XMLHttpRequest 对象以 0 â 1 â 2 â 3 â ⦠â 3 â 4 ç顺åºå¨å®ä»¬ä¹é´è½¬åãæ¯å½éè¿ç½ç»æ¥æ¶å°ä¸ä¸ªæ°æ®å
ï¼å°±ä¼éå¤ä¸æ¬¡ç¶æ 3ã
æä»¬å¯ä»¥ä½¿ç¨ readystatechange äºä»¶æ¥è·è¸ªå®ä»¬ï¼
xhr.onreadystatechange = function() {
if (xhr.readyState == 3) {
// å è½½ä¸
}
if (xhr.readyState == 4) {
// 请æ±å®æ
}
};
ä½ å¯è½å¨é常èç代ç 䏿¾å° readystatechange è¿æ ·çäºä»¶çå¬å¨ï¼å®çå卿¯æåå²åå çï¼å 为æ¾ç»æå¾é¿ä¸æ®µæ¶é´é½æ²¡æ load 以åå
¶ä»äºä»¶ãå¦ä»ï¼å®å·²è¢« load/error/progress äºä»¶å¤çç¨åºææ¿ä»£ã
䏿¢è¯·æ±ï¼Abortingï¼
æä»¬å¯ä»¥éæ¶ç»æ¢è¯·æ±ãè°ç¨ xhr.abort() å³å¯ï¼
xhr.abort(); // ç»æ¢è¯·æ±
å®ä¼è§¦å abort äºä»¶ï¼ä¸ xhr.status å为 0ã
åæ¥è¯·æ±
å¦æå¨ open æ¹æ³ä¸å°ç¬¬ä¸ä¸ªåæ° async 设置为 falseï¼é£ä¹è¯·æ±å°±ä¼ä»¥åæ¥çæ¹å¼è¿è¡ã
æ¢å¥è¯è¯´ï¼JavaScript æ§è¡å¨ send() 夿åï¼å¹¶å¨æ¶å°ååºåæ¢å¤æ§è¡ãè¿æç¹å¿å alert æ prompt å½ä»¤ã
ä¸é¢æ¯éåç示ä¾ï¼open ç第ä¸ä¸ªåæ°ä¸º falseï¼
let xhr = new XMLHttpRequest();
xhr.open('GET', '/article/xmlhttprequest/hello.txt', false);
try {
xhr.send();
if (xhr.status != 200) {
alert(`Error ${xhr.status}: ${xhr.statusText}`);
} else {
alert(xhr.response);
}
} catch(err) { // ä»£æ¿ onerror
alert("Request failed");
}
è¿çèµ·æ¥å¥½åä¸éï¼ä½æ¯å¾å°ä½¿ç¨åæ¥è°ç¨ï¼å 为å®ä»¬ä¼é»å¡é¡µé¢å ç JavaScriptï¼ç´å°å è½½å®æãå¨æäºæµè§å¨ä¸ï¼æ»å¨å¯è½æ æ³æ£å¸¸è¿è¡ã妿ä¸ä¸ªåæ¥è°ç¨æ§è¡æ¶é´è¿é¿ï¼æµè§å¨å¯è½ä¼å»ºè®®å ³éâæèµ·ï¼hangingï¼âçç½é¡µã
XMLHttpRequest çå¾å¤é«çº§åè½å¨åæ¥è¯·æ±ä¸é½ä¸å¯ç¨ï¼ä¾å¦åå
¶ä»ååèµ·è¯·æ±æè
设置è¶
æ¶ãå¹¶ä¸ï¼æ£å¦ä½ æçå°çï¼æ²¡æè¿åº¦æç¤ºã
åºäºè¿äºåå ï¼åæ¥è¯·æ±ä½¿ç¨çé常å°ï¼å ä¹ä»ä¸ä½¿ç¨ãå¨è¿æä»¬å°±ä¸å讨论å®äºã
HTTP-header
XMLHttpRequest å
许åéèªå®ä¹ headerï¼å¹¶ä¸å¯ä»¥ä»ååºä¸è¯»å headerã
HTTP-header æä¸ç§æ¹æ³ï¼
setRequestHeader(name, value)-
使ç¨ç»å®ç
nameåvalue设置 request headerãä¾å¦ï¼
xhr.setRequestHeader('Content-Type', 'application/json');Header çéå¶ä¸äº header æ¯ç±æµè§å¨ä¸é¨ç®¡ççï¼ä¾å¦
RefereråHostã 宿´åè¡¨è¯·è§ è§èã为äºç¨æ·å®å ¨å请æ±çæ£ç¡®æ§ï¼
XMLHttpRequestä¸å è®¸æ´æ¹å®ä»¬ãä¸è½ç§»é¤ headerXMLHttpRequestçå¦ä¸ä¸ªç¹ç¹æ¯ä¸è½æ¤ésetRequestHeaderã䏿¦è®¾ç½®äº headerï¼å°±æ æ³æ¤éäºãå ¶ä»è°ç¨ä¼å header 䏿·»å ä¿¡æ¯ï¼ä½ä¸ä¼è¦çå®ã
ä¾å¦ï¼
xhr.setRequestHeader('X-Auth', '123'); xhr.setRequestHeader('X-Auth', '456'); // header å°æ¯ï¼ // X-Auth: 123, 456 getResponseHeader(name)-
è·åå ·æç»å®
nameç headerï¼Set-CookieåSet-Cookie2é¤å¤ï¼ãä¾å¦ï¼
xhr.getResponseHeader('Content-Type') getAllResponseHeaders()-
è¿åé¤
Set-CookieåSet-Cookie2å¤çææ response headerãheader 以åè¡å½¢å¼è¿åï¼ä¾å¦ï¼
Cache-Control: max-age=31536000 Content-Length: 4260 Content-Type: image/png Date: Sat, 08 Sep 2012 16:53:16 GMTheader ä¹é´çæ¢è¡ç¬¦å§ç»ä¸º
"\r\n"ï¼ä¸ä¾èµäºæä½ç³»ç»ï¼ï¼æä»¥æä»¬å¯ä»¥å¾å®¹æå°å°å ¶æå为åç¬ç headerãname å value ä¹é´æ»æ¯ä»¥åå·åè·ä¸ä¸ªç©ºæ ¼": "åéãè¿æ¯æ åæ ¼å¼ãå æ¤ï¼å¦ææä»¬æ³è¦è·åå ·æ name/value 对ç对象ï¼åéè¦ç¨ä¸ç¹ JavaScript ä»£ç æ¥å¤çå®ä»¬ã
åè¿æ ·ï¼åè®¾å¦æä¸¤ä¸ª header å ·æç¸åçåç§°ï¼é£ä¹åè å°±ä¼è¦çåè ï¼ï¼
let headers = xhr .getAllResponseHeaders() .split('\r\n') .reduce((result, current) => { let [name, value] = current.split(': '); result[name] = value; return result; }, {}); // headers['Content-Type'] = 'image/png'
POSTï¼FormData
è¦å»ºç«ä¸ä¸ª POST 请æ±ï¼æä»¬å¯ä»¥ä½¿ç¨å 建ç FormData 对象ã
è¯æ³ä¸ºï¼
let formData = new FormData([form]); // å建ä¸ä¸ªå¯¹è±¡ï¼å¯ä»¥éæ©ä» <form> ä¸è·åæ°æ®
formData.append(name, value); // éå ä¸ä¸ªå段
æä»¬å建å®ï¼å¯ä»¥éæ©ä»ä¸ä¸ªè¡¨åä¸è·åæ°æ®ï¼å¦æéè¦ï¼è¿å¯ä»¥ append æ´å¤å段ï¼ç¶åï¼
xhr.open('POST', ...)ââ 使ç¨POSTæ¹æ³ãxhr.send(formData)å°è¡¨ååéå°æå¡å¨ã
ä¾å¦ï¼
<form name="person">
<input name="name" value="John">
<input name="surname" value="Smith">
</form>
<script>
// ä»è¡¨åé¢å¡«å
FormData
let formData = new FormData(document.forms.person);
// éå ä¸ä¸ªå段
formData.append("middle", "Lee");
// å°å
¶åéåºå»
let xhr = new XMLHttpRequest();
xhr.open("POST", "/article/xmlhttprequest/post/user");
xhr.send(formData);
xhr.onload = () => alert(xhr.response);
</script>
以 multipart/form-data ç¼ç åé表åã
æè
ï¼å¦ææä»¬æ´å欢 JSONï¼é£ä¹å¯ä»¥ä½¿ç¨ JSON.stringify 并以å符串形å¼åéã
åªæ¯ï¼ä¸è¦å¿è®°è®¾ç½® header Content-Type: application/jsonï¼åªè¦æäºå®ï¼å¾å¤æå¡ç«¯æ¡æ¶é½è½èªå¨è§£ç JSONï¼
let xhr = new XMLHttpRequest();
let json = JSON.stringify({
name: "John",
surname: "Smith"
});
xhr.open("POST", '/submit')
xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
xhr.send(json);
.send(body) æ¹æ³å°±åä¸ä¸ªé常æé£æ§çå¨ç©ãå®å ä¹å¯ä»¥åéä»»ä½ bodyï¼å
æ¬ Blob å BufferSource 对象ã
ä¸ä¼ è¿åº¦
progress äºä»¶ä»
å¨ä¸è½½é¶æ®µè§¦åã
ä¹å°±æ¯è¯´ï¼å¦ææä»¬ POST ä¸äºå
容ï¼XMLHttpRequest é¦å
ä¸ä¼ æä»¬çæ°æ®ï¼request bodyï¼ï¼ç¶åä¸è½½ååºã
妿æä»¬è¦ä¸ä¼ çä¸è¥¿å¾å¤§ï¼é£ä¹æä»¬è¯å®ä¼å¯¹è·è¸ªä¸ä¼ è¿åº¦æå
´è¶£ã使¯ xhr.onprogress å¨è¿éå¹¶ä¸èµ·ä½ç¨ã
è¿éæå¦ä¸ä¸ªå¯¹è±¡ï¼å®æ²¡ææ¹æ³ï¼å®ä¸é¨ç¨äºè·è¸ªä¸ä¼ äºä»¶ï¼xhr.uploadã
å®ä¼çæäºä»¶ï¼ç±»ä¼¼äº xhrï¼ä½æ¯ xhr.upload ä»
å¨ä¸ä¼ æ¶è§¦åå®ä»¬ï¼
loadstartââ ä¸ä¼ å¼å§ãprogressââ ä¸ä¼ æé´å®æè§¦åãabortââ ä¸ä¼ 䏿¢ãerrorââ é HTTP é误ãloadââ ä¸ä¼ æå宿ãtimeoutââ ä¸ä¼ è¶ æ¶ï¼å¦æè®¾ç½®äºtimeout屿§ï¼ãloadendââ ä¸ä¼ å®æï¼æ 论æåè¿æ¯ errorã
handler 示ä¾ï¼
xhr.upload.onprogress = function(event) {
alert(`Uploaded ${event.loaded} of ${event.total} bytes`);
};
xhr.upload.onload = function() {
alert(`Upload finished successfully.`);
};
xhr.upload.onerror = function() {
alert(`Error during the upload: ${xhr.status}`);
};
è¿æ¯ä¸ä¸ªçå®ç¤ºä¾ï¼å¸¦æè¿åº¦æç¤ºçæä»¶ä¸ä¼ ï¼
<input type="file" onchange="upload(this.files[0])">
<script>
function upload(file) {
let xhr = new XMLHttpRequest();
// è·è¸ªä¸ä¼ è¿åº¦
xhr.upload.onprogress = function(event) {
console.log(`Uploaded ${event.loaded} of ${event.total}`);
};
// è·è¸ªå®æï¼æ 论æåä¸å¦
xhr.onloadend = function() {
if (xhr.status == 200) {
console.log("success");
} else {
console.log("error " + this.status);
}
};
xhr.open("POST", "/article/xmlhttprequest/post/upload");
xhr.send(file);
}
</script>
è·¨æºè¯·æ±
XMLHttpRequest å¯ä»¥ä½¿ç¨å fetch ç¸åç CORS çç¥è¿è¡è·¨æºè¯·æ±ã
å°±å fetch 䏿 ·ï¼é»è®¤æ
åµä¸ä¸ä¼å° cookie å HTTP ææåéå°å
¶ä»åãè¦å¯ç¨å®ä»¬ï¼å¯ä»¥å° xhr.withCredentials 设置为 trueï¼
let xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.open('POST', 'http://anywhere.com/request');
...
æå ³è·¨æº header ç详ç»ä¿¡æ¯ï¼è¯·è§ Fetchï¼è·¨æºè¯·æ± ä¸ç« ã
æ»ç»
ä½¿ç¨ XMLHttpRequest ç GET 请æ±çå
¸å代ç ï¼
let xhr = new XMLHttpRequest();
xhr.open('GET', '/my/url');
xhr.send();
xhr.onload = function() {
if (xhr.status != 200) { // HTTP error?
// å¤ç error
alert( 'Error: ' + xhr.status);
return;
}
// è·åæ¥èª xhr.response çååº
};
xhr.onprogress = function(event) {
// æ¥åè¿åº¦
alert(`Loaded ${event.loaded} of ${event.total}`);
};
xhr.onerror = function() {
// å¤çé HTTP errorï¼ä¾å¦ç½ç»ä¸æï¼
};
å®é ä¸è¿æå¾å¤äºä»¶ï¼å¨ ç°ä»£è§è ä¸æè¯¦ç»åè¡¨ï¼æçå½å¨ææåºï¼ï¼
loadstartââ 请æ±å¼å§ãprogressââ ä¸ä¸ªååºæ°æ®å å°è¾¾ï¼æ¤æ¶æ´ä¸ª response body é½å¨responseä¸ãabortââ è°ç¨xhr.abort()åæ¶äºè¯·æ±ãerrorââ åçè¿æ¥é误ï¼ä¾å¦ï¼åé误ãä¸ä¼åçè¯¸å¦ 404 è¿ç±»ç HTTP é误ãloadââ è¯·æ±æå宿ãtimeoutââ ç±äºè¯·æ±è¶ æ¶èåæ¶äºè¯¥è¯·æ±ï¼ä» åçå¨è®¾ç½®äº timeout çæ åµä¸ï¼ãloadendââ å¨loadï¼errorï¼timeoutæabortä¹å触åã
errorï¼abortï¼timeout å load äºä»¶æ¯äºæ¥çãå
¶ä¸åªæä¸ç§å¯è½åçã
æå¸¸ç¨çäºä»¶æ¯å è½½å®æï¼loadï¼ï¼å 载失败ï¼errorï¼ï¼æè
æä»¬å¯ä»¥ä½¿ç¨å个 loadend å¤çç¨åºå¹¶æ£æ¥è¯·æ±å¯¹è±¡ xhr ç屿§ï¼ä»¥æ¥çåçäºä»ä¹ã
æä»¬è¿äºè§£äºå¦ä¸ä¸ªäºä»¶ï¼readystatechangeãç±äºåå²åå ï¼å®æ©å¨è§èå¶å®ä¹åå°±åºç°äºãå¦ä»æä»¬å·²ç»æ é使ç¨å®äºï¼æä»¬å¯ä»¥ç¨æ°çäºä»¶ä»£æ¿å®ï¼ä½é常å¯ä»¥å¨æ§ç代ç 䏿¾å°å®ã
妿æä»¬éè¦ä¸é¨è·è¸ªä¸ä¼ ï¼é£ä¹æä»¬åºè¯¥å¨ xhr.upload 对象ä¸çå¬ç¸åçäºä»¶ã
è¯è®º
<code>æ ç¾æå ¥åªæå 个è¯ç代ç ï¼æå ¥å¤è¡ä»£ç å¯ä»¥ä½¿ç¨<pre>æ ç¾ï¼å¯¹äºè¶ è¿ 10 è¡ç代ç ï¼å»ºè®®ä½ ä½¿ç¨æ²ç®±ï¼plnkrï¼JSBinï¼codepenâ¦ï¼