fetch æ¹æ³å
许å»è·è¸ª ä¸è½½ è¿åº¦ã
请注æï¼å°ç®å为æ¢ï¼fetch æ¹æ³æ æ³è·è¸ª ä¸ä¼ è¿åº¦ã对äºè¿ä¸ªç®çï¼è¯·ä½¿ç¨ XMLHttpRequestï¼æä»¬å¨åé¢ç« èä¼è®²å°ã
è¦è·è¸ªä¸è½½è¿åº¦ï¼æä»¬å¯ä»¥ä½¿ç¨ response.body 屿§ã宿¯ ReadableStream ââ ä¸ä¸ªç¹æ®ç对象ï¼å®å¯ä»¥éåï¼chunkï¼æä¾ bodyãå¨ Streams API è§è䏿坹 ReadableStream çè¯¦ç»æè¿°ã
ä¸ response.text()ï¼response.json() åå
¶ä»æ¹æ³ä¸åï¼response.body ç»äºäºå¯¹è¿åº¦è¯»åçå®å
¨æ§å¶ï¼æä»¬å¯ä»¥éæ¶è®¡ç®ä¸è½½äºå¤å°ã
è¿æ¯ä» response.body 读å response ç示ä¾ä»£ç ï¼
// ä»£æ¿ response.json() 以åå
¶ä»æ¹æ³
const reader = response.body.getReader();
// å¨ body ä¸è½½æ¶ï¼ä¸ç´ä¸ºæ é循ç¯
while(true) {
// 彿åä¸åä¸è½½å®ææ¶ï¼done å¼ä¸º true
// value æ¯ååèç Uint8Array
const {done, value} = await reader.read();
if (done) {
break;
}
console.log(`Received ${value.length} bytes`)
}
await reader.read() è°ç¨çç»ææ¯ä¸ä¸ªå
·æä¸¤ä¸ªå±æ§ç对象ï¼
doneââ å½è¯»å宿æ¶ä¸ºtrueï¼å¦å为falseãvalueââ åèçç±»ååæ°ç»ï¼Uint8Arrayã
Streams API è¿æè¿°äºå¦æä½¿ç¨ for await..of 循ç¯å¼æ¥è¿ä»£ ReadableStreamï¼ä½æ¯ç®å为æ¢ï¼å®è¿æªå¾å°å¾å¥½çæ¯æï¼åè§ æµè§å¨é®é¢ï¼ï¼æä»¥æä»¬ä½¿ç¨äº while 循ç¯ã
æä»¬å¨å¾ªç¯ä¸æ¥æ¶ååºåï¼response chunkï¼ï¼ç´å°å è½½å®æï¼ä¹å°±æ¯ï¼ç´å° done 为 trueã
è¦å°è¿åº¦æå°åºæ¥ï¼æä»¬åªéè¦å°æ¯ä¸ªæ¥æ¶å°ççæ®µ value çé¿åº¦ï¼lengthï¼å å° counter å³å¯ã
è¿æ¯è·åååºï¼å¹¶å¨æ§å¶å°ä¸è®°å½è¿åº¦ç宿´å·¥ä½ç¤ºä¾ï¼ä¸é¢ææ´å¤è¯´æï¼
// Step 1ï¼å¯å¨ fetchï¼å¹¶è·å¾ä¸ä¸ª reader
let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits?per_page=100');
const reader = response.body.getReader();
// Step 2ï¼è·å¾æ»é¿åº¦ï¼lengthï¼
const contentLength = +response.headers.get('Content-Length');
// Step 3ï¼è¯»åæ°æ®
let receivedLength = 0; // å½åæ¥æ¶å°äºè¿ä¹å¤åè
let chunks = []; // æ¥æ¶å°çäºè¿å¶åçæ°ç»ï¼å
æ¬ bodyï¼
while(true) {
const {done, value} = await reader.read();
if (done) {
break;
}
chunks.push(value);
receivedLength += value.length;
console.log(`Received ${receivedLength} of ${contentLength}`)
}
// Step 4ï¼å°åè¿æ¥å°å个 Uint8Array
let chunksAll = new Uint8Array(receivedLength); // (4.1)
let position = 0;
for(let chunk of chunks) {
chunksAll.set(chunk, position); // (4.2)
position += chunk.length;
}
// Step 5ï¼è§£ç æå符串
let result = new TextDecoder("utf-8").decode(chunksAll);
// æä»¬å®æå¦ï¼
let commits = JSON.parse(result);
alert(commits[0].author.login);
让æä»¬ä¸æ¥æ¥è§£éä¸è¿ä¸ªè¿ç¨ï¼
-
æä»¬åå¾å¸¸ä¸æ ·æ§è¡
fetchï¼ä½ä¸æ¯è°ç¨response.json()ï¼èæ¯è·å¾äºä¸ä¸ªæµè¯»åå¨ï¼stream readerï¼response.body.getReader()ã请注æï¼æä»¬ä¸è½åæ¶ä½¿ç¨è¿ä¸¤ç§æ¹æ³æ¥è¯»åç¸åçååºãè¦ä¹ä½¿ç¨æµè¯»åå¨ï¼è¦ä¹ä½¿ç¨ reponse æ¹æ³æ¥è·åç»æã
-
å¨è¯»åæ°æ®ä¹åï¼æä»¬å¯ä»¥ä»
Content-Lengthheader ä¸å¾å°å®æ´çååºé¿åº¦ãè·¨æºè¯·æ±ä¸å¯è½ä¸åå¨è¿ä¸ª headerï¼è¯·åè§ Fetchï¼è·¨æºè¯·æ±ï¼ï¼å¹¶ä¸ä»ææ¯ä¸è®²ï¼æå¡å¨å¯ä»¥ä¸è®¾ç½®å®ã使¯é常æ åµä¸å®é½ä¼å¨é£éã
-
è°ç¨
await reader.read()ï¼ç´å°å®å®æãæä»¬å°ååºåæ¶éå°æ°ç»
chunksä¸ãè¿å¾éè¦ï¼å 为å¨ä½¿ç¨å®ï¼consumedï¼ååºåï¼æä»¬å°æ æ³ä½¿ç¨response.json()æè å ¶ä»æ¹å¼ï¼ä½ å¯ä»¥è¯è¯ï¼å°ä¼åºç° errorï¼å»âéæ°è¯»åâå®ã -
æåï¼æä»¬æäºä¸ä¸ª
chunksââ ä¸ä¸ªUint8Arrayåèåæ°ç»ãæä»¬éè¦å°è¿äºååå¹¶æä¸ä¸ªç»æãä½ä¸å¹¸çæ¯ï¼æ²¡æåä¸ªæ¹æ³å¯ä»¥å°å®ä»¬ä¸²èèµ·æ¥ï¼æä»¥è¿ééè¦ä¸äºä»£ç æ¥å®ç°ï¼- æä»¬å建
chunksAll = new Uint8Array(receivedLength)ââ ä¸ä¸ªå ·ææææ°æ®ååå¹¶åçé¿åº¦çåç±»åæ°ç»ã - ç¶å使ç¨
.set(chunk, position)æ¹æ³ï¼ä»æ°ç»ä¸ä¸ä¸ªä¸ªå°å¤å¶è¿äºchunkã
- æä»¬å建
-
æä»¬çç»æç°å¨å¨åå¨
chunksAllä¸ãä½å®æ¯ä¸ä¸ªåèæ°ç»ï¼ä¸æ¯å符串ãè¦å建ä¸ä¸ªåç¬¦ä¸²ï¼æä»¬éè¦è§£æè¿äºåèãå¯ä»¥ä½¿ç¨å 建ç TextDecoder å¯¹è±¡å®æãç¶åï¼æä»¬å¯ä»¥
JSON.parseå®ï¼å¦ææå¿ è¦çè¯ã妿æä»¬éè¦çæ¯äºè¿å¶å 容è䏿¯å符串å¢ï¼è¿æ´ç®åãç¨ä¸é¢è¿è¡ä»£ç æ¿æ¢æç¬¬ 4 å第 5 æ¥ï¼è¿è¡ä»£ç 仿æåå建ä¸ä¸ª
Blobï¼let blob = new Blob(chunks);
æåï¼æä»¬å¾å°äºç»æï¼ä»¥å符串æ blob çå½¢å¼è¡¨ç¤ºï¼ä»ä¹æ¹ä¾¿å°±ç¨ä»ä¹ï¼ï¼å¹¶å¨è¿ç¨ä¸å¯¹è¿åº¦è¿è¡äºè·è¸ªã
å强è°ä¸éï¼è¿ä¸è½ç¨äº ä¸ä¼ è¿ç¨ï¼ç°å¨æ æ³éè¿ fetch è·åï¼ï¼ä»
ç¨äº ä¸è½½ è¿ç¨ã
å¦å¤ï¼å¦æå¤§å°æªç¥ï¼æä»¬åºè¯¥æ£æ¥å¾ªç¯ä¸ç receivedLengthï¼ä¸æ¦è¾¾å°ä¸å®çéå¶å°±å°å
¶ä¸æãè¿æ · chunks å°±ä¸ä¼æº¢åºå
åäºã
è¯è®º
<code>æ ç¾æå ¥åªæå 个è¯ç代ç ï¼æå ¥å¤è¡ä»£ç å¯ä»¥ä½¿ç¨<pre>æ ç¾ï¼å¯¹äºè¶ è¿ 10 è¡ç代ç ï¼å»ºè®®ä½ ä½¿ç¨æ²ç®±ï¼plnkrï¼JSBinï¼codepenâ¦ï¼