* @param {string} url * @param {!WritableStreamDefaultWriter} writer * @return {!Promise}
(url, writer)
| 409 | * @return {!Promise} |
| 410 | */ |
| 411 | function streamDocument(url, writer) { |
| 412 | // Try native first. |
| 413 | if (window.fetch && window.TextDecoder && window.ReadableStream) { |
| 414 | return fetch(url).then((response) => { |
| 415 | // This should be a lot simpler with transforming streams and pipes, |
| 416 | // but, TMK, these are not supported anywhere yet. |
| 417 | const /** !ReadableStreamDefaultReader */ reader = |
| 418 | response.body.getReader(); |
| 419 | const decoder = new TextDecoder(); |
| 420 | function readChunk(chunk) { |
| 421 | const text = decoder.decode(chunk.value || new Uint8Array(), { |
| 422 | stream: !chunk.done, |
| 423 | }); |
| 424 | if (text) { |
| 425 | writer.write(text); |
| 426 | } |
| 427 | if (chunk.done) { |
| 428 | writer.close(); |
| 429 | } else { |
| 430 | return reader.read().then(readChunk); |
| 431 | } |
| 432 | } |
| 433 | return reader.read().then(readChunk); |
| 434 | }); |
| 435 | } |
| 436 | |
| 437 | // Polyfill via XHR. |
| 438 | return new Promise((resolve, reject) => { |
| 439 | const xhr = new XMLHttpRequest(); |
| 440 | xhr.open('GET', url, true); |
| 441 | xhr.setRequestHeader('Accept', 'text/html'); |
| 442 | let pos = 0; |
| 443 | xhr.onreadystatechange = () => { |
| 444 | if (xhr.readyState < /* STATUS_RECEIVED */ 2) { |
| 445 | return; |
| 446 | } |
| 447 | if (xhr.status < 100 || xhr.status > 599) { |
| 448 | xhr.onreadystatechange = null; |
| 449 | reject(new Error(`Unknown HTTP status ${xhr.status}`)); |
| 450 | return; |
| 451 | } |
| 452 | if ( |
| 453 | xhr.readyState == /* LOADING */ 3 || |
| 454 | xhr.readyState == /* COMPLETE */ 4 |
| 455 | ) { |
| 456 | const s = xhr.responseText; |
| 457 | const chunk = s.substring(pos); |
| 458 | pos = s.length; |
| 459 | writer.write(chunk); |
| 460 | if (xhr.readyState == /* COMPLETE */ 4) { |
| 461 | writer.close().then(resolve); |
| 462 | } |
| 463 | } |
| 464 | }; |
| 465 | xhr.onerror = () => { |
| 466 | reject(new Error('Network failure')); |
| 467 | }; |
| 468 | xhr.onabort = () => { |