JavaScript éçºè ã¨ãã¦ããããã¯ã¼ã¯ãä»ãã¦åä¿¡ãããã¼ã¿ã®ã¹ããªã¼ã ããã£ã³ã¯ãã¨ã«ããã°ã©ã ã§èªã¿åããæä½ãããã¨ã¯ã¨ã¦ã便å©ã§ããããããã¹ããªã¼ã API ã®èªã¿åãå¯è½ãªã¹ããªã¼ã ã®æ©è½ã¯ã©ã®ããã«ä½¿ç¨ããã®ã§ããããããã®è¨äºã§ã¯ããã®åºæ¬ã«ã¤ãã¦èª¬æãã¾ãã
ã¡ã¢: ãã®è¨äºã¯ãèªè ãèªã¿åãå¯è½ãªã¹ããªã¼ã ã®ç¨éãçè§£ããé«ã¬ãã«ã®æ¦å¿µãçè§£ãã¦ãããã¨ãåæã¨ãã¦ãã¾ãã ããã§ãªãå ´åã¯ãã¾ãã¹ããªã¼ã ã®æ¦å¿µã¨ä½¿ç¨æ¹æ³ã®æ¦è¦ã¨ã¹ããªã¼ã API ã®æ¦å¿µã®è¨äºãèªãã§ãããæ»ã£ã¦ãããã¨ããå§ããã¾ãã
ã¡ã¢: æ¸ãè¾¼ã¿å¯è½ãªã¹ããªã¼ã ã«é¢ããæ å ±ãæ¢ãã¦ããã®ã§ããã°ãæ¸ãè¾¼ã¿å¯è½ãªã¹ããªã¼ã ã®ä½¿ç¨ãè¦ã¦ã¿ã¦ãã ããã
ããã¤ãã®ä¾ãè¦ã¤ãããã®è¨äºã§ã¯ãdom-examples/streams ãªãã¸ããªã¼ããåå¾ãããã¾ãã¾ãªä¾ãè¦ã¦ããã¾ãã ããã«ã¯å®å ¨ãªã½ã¼ã¹ã³ã¼ãã¨ä¾ã¸ã®ãªã³ã¯ãããã¾ãã
ãã§ãããã¹ããªã¼ã ã¨ãã¦æ¶è²»ããFetch API ã¯ããããã¯ã¼ã¯ãéãã¦ãªã½ã¼ã¹ããã§ãããããã¨ãã§ãã XHR ã«ä»£ããç¾ä»£çãªæ¹æ³ãæä¾ãã¾ããããã«ã¯å¤ãã®å©ç¹ããããå®ã«ç´ æ´ãããã®ã¯ããã©ã¦ã¶ã¼ãæè¿ããã§ããããã¬ã¹ãã³ã¹ãèªã¿åãå¯è½ãªã¹ããªã¼ã ã¨ãã¦æ¶è²»ããæ©è½ã追å ãããã¨ã§ãã
Request.body
㨠Response.body
ããããã£ãå©ç¨ã§ãã¾ããããããã¯æ¬ä½ã®ä¸èº«ãèªã¿åãå¯è½ãªã¹ããªã¼ã ã¨ãã¦åå¾ã§ããã²ãã¿ã¼ã§ãã
åç´ãªã¹ããªã¼ã ãã³ãï¼Simple stream pumpï¼ã®ä¾ã示ãã¦ããããã«ï¼ã©ã¤ããåç
§ï¼ããããå
¬éãããã¨ã¯ã次ã®ããã«å¿çã® body
ããããã£ã«ã¢ã¯ã»ã¹ããã ãã®ãã¨ã§ãã
// å
ã®ç»åãèªã¿åã
fetch("./tortoise.png")
// ãã® body ã ReadableStream ã¨ãã¦åå¾
.then((response) => response.body);
ããã«ããã ReadableStream
ãªãã¸ã§ã¯ããæä¾ããã¾ãã
ã¹ããªã¼ã ããæ¬ä½ãå¾ããã¾ãããã¹ããªã¼ã ãèªãã«ã¯ããªã¼ãã¼ãåãä»ããå¿
è¦ãããã¾ãã ããã¯ã ReadableStream.getReader()
ã¡ã½ããã使ç¨ãã¦è¡ããã¾ãã
// å
ã®ç»åããã§ãã
fetch("./tortoise.png")
// ãã® body ã ReadableStream ã¨ãã¦åå¾
.then((response) => response.body)
.then((body) => {
const reader = body.getReader();
// â¦
});
ãã®ã¡ã½ãããå¼ã³åºãã¨ããªã¼ãã¼ã使ãããã¹ããªã¼ã ã«ããã¯ããã¾ãããã®ãªã¼ãã¼ãè§£æ¾ãããã¾ã§ãä»ã®ãªã¼ãã¼ã¯ãã®ã¹ããªã¼ã ãèªã¿åããã¨ãã§ãã¾ããã è§£æ¾ããã«ã¯ãä¾ãã° ReadableStreamDefaultReader.releaseLock()
ãå¼ã³åºãã¾ãã
ã¾ããresponse.body
ã¯åæçã§ããããããã¹ãå¿
è¦ã¨ããªããããåã®ä¾ã 1 ã¹ãããæ¸ãããã¨ãã§ãããã¨ã«æ³¨æãã¦ãã ããã
// å
ã®ç»åããã§ãã
fetch("./tortoise.png")
// ãã® body ã ReadableStream ã¨ãã¦åå¾
.then((response) => {
const reader = response.body.getReader();
// â¦
});
ã¹ããªã¼ã ãèªã¿åã
ãªã¼ãã¼ãåãä»ããããReadableStreamDefaultReader.read()
ã¡ã½ããã使ç¨ãã¦ã¹ããªã¼ã ãããã¼ã¿ãã£ã³ã¯ãèªã¿åããã¨ãã§ãã¾ãã ããã«ãããã¹ããªã¼ã ãã 1 ã¤ãã£ã³ã¯ãèªã¿åã£ã¦ã好ããªãã¨ãå®è¡ã§ãã¾ãã ä¾ãã°ãåç´ãªã¹ããªã¼ã ãã³ãã®ä¾ã§ã¯ãæ°ããã«ã¹ã¿ã ReadableStream
ã§åãã£ã³ã¯ããã¥ã¼ã«å
¥ãï¼ããã«ã¤ãã¦ã¯æ¬¡ã®ã»ã¯ã·ã§ã³ã§è©³ãã説æãã¾ãï¼ãããããæ°ãã Response
ã使ããBlob
ã¨ãã¦ä½¿ç¨ãã URL.createObjectURL()
ã使ç¨ãã¦ãã® blob ãããªãã¸ã§ã¯ã URL ãåå¾ããããã <img>
è¦ç´ ã§ç»é¢ã«è¡¨ç¤ºãã¦ãå
ã®ãã§ããããç»åã®ã³ãã¼ã广çã«ä½æãã¾ãã
// å
ã®ç»åãåå¾
fetch("./tortoise.png")
// æ¬ä½ã ReadableStream ã¨ãã¦åå¾
.then((response) => {
const reader = response.body.getReader();
return new ReadableStream({
start(controller) {
return pump();
function pump() {
return reader.read().then(({ done, value }) => {
// ãã¼ã¿ãæ¶è²»ããå¿
è¦ããªããªã£ãããã¹ããªã¼ã ãéãã
if (done) {
controller.close();
return;
}
// 次ã®ãã¼ã¿ãã£ã³ã¯ã対象ã®ã¹ããªã¼ã ã®ãã¥ã¼ã«å
¥ãã
controller.enqueue(value);
return pump();
});
}
},
});
})
// æ°ããã¬ã¹ãã³ã¹ãã¹ããªã¼ã ã®å¤ã«ä½æ
.then((stream) => new Response(stream))
// ã¬ã¹ãã³ã¹ã®ãªãã¸ã§ã¯ã URL ã使
.then((response) => response.blob())
.then((blob) => URL.createObjectURL(blob))
// Update image
.then((url) => console.log((image.src = url)))
.catch((err) => console.error(err));
read()
ã®ä½¿ç¨æ¹æ³ã詳ããè¦ã¦ã¿ã¾ãããã ä¸è¨ã® pump()
颿°ã§ã¯ãæåã«çµæãªãã¸ã§ã¯ããå«ããããã¹ãè¿ã read()
ãå¼ã³åºãã¾ãã çµæãªãã¸ã§ã¯ãã«ã¯ã次ã®ããã«èªã¿åãã®çµæã { done, value }
ã®å½¢å¼ã§å«ã¾ãã¦ãã¾ãã
reader.read().then(({ done, value }) => {
/* ⦠*/
});
çµæã¯ã次㮠3 ã¤ã®ç°ãªãå½¢å¼ã®ããããã«ãªãã¾ãã
{ value: theChunk, done: false }
ã®å½¢å¼ã®ãªãã¸ã§ã¯ãã§ãããã¹ãå±¥è¡ããã¾ãã{ value: undefined, done: true }
ã¨ããå½¢å¼ã®ãªãã¸ã§ã¯ãã§ãããã¹ãå±¥è¡ããã¾ããæ¬¡ã«ã done
ã true
ã§ãããã©ããã確èªãã¾ãã ãã®å ´åãèªã¿è¾¼ããã£ã³ã¯ã¯ãããªãã®ã§ï¼å¤ã¯ undefined
ã§ãï¼ã颿°ããæ»ããReadableStreamDefaultController.close()
ã§ã«ã¹ã¿ã ã¹ããªã¼ã ãéãã¾ãã
if (done) {
controller.close();
return;
}
ã¡ã¢: close()
ã¯ãããã§èª¬æãã¦ããå
ã®ã¹ããªã¼ã ã§ã¯ãªããæ°ããã«ã¹ã¿ã ã¹ããªã¼ã ã®ä¸é¨ã§ãã æ¬¡ã®ç¯ã§ã«ã¹ã¿ã ã¹ããªã¼ã ã«ã¤ãã¦è©³ãã説æãã¾ãã
done
ã true
ã§ãªãå ´åãèªã¿è¾¼ãã æ°ãããã£ã³ã¯ï¼çµæãªãã¸ã§ã¯ãã® value
ããããã£ã«å«ã¾ããï¼ãå¦çãã¦ãããå度 pump()
颿°ãå¼ã³åºãã¦æ¬¡ã®ãã£ã³ã¯ãèªã¿è¾¼ã¿ã¾ãã
// 次ã®ãã¼ã¿ãã£ã³ã¯ã対象ã®ã¹ããªã¼ã ã®ãã¥ã¼ã«å
¥ãã¾ã
controller.enqueue(value);
return pump();
ããã¯ãã¹ããªã¼ã ã®ãªã¼ãã¼ã使ç¨ããã¨ãã«ç¤ºãããæ¬¡ã®ãããªæ¨æºãã¿ã¼ã³ã§ãã
å®éã«ããã³ãããå®è¡ããã³ã¼ãããã¹ã¦é¤å»ãããã¨ãã³ã¼ãã¯æ¬¡ã®ããã«ä¸è¬åãããããããã¾ããã
fetch("http://example.com/somefile.txt")
// æ¬ä½ã ReadableStream ã¨ãã¦åãåã
.then((response) => {
const reader = response.body.getReader();
// read() ã¯å¤ãåãåã£ãã¨ãã«è§£æ±ºãããããã¹ãè¿ã
reader.read().then(function pump({ done, value }) {
if (done) {
// ãã¼ã¿ã®æå¾ã®ãã£ã³ã¯ã§ä½ããè¡ãããªã¼ãã¼ãçµäºãã
return;
}
// ããã§ãªãå ´åã¯ãããã§ç¾å¨ã®ãã£ã³ã¯ãå¦çãã
// ããã«èªã¿é²ãã¦ããã®é¢æ°ãããä¸åº¦å¼ã³åºã
return reader.read().then(pump);
});
})
.catch((err) => console.error(err));
ã¡ã¢: ãã®é¢æ°ã¯ pump()
ãèªåèªèº«ãå¼ã³åºããã®ããã«è¦ããæ·±ãå帰ã«ã¤ãªããå¯è½æ§ãããã¾ãããããã pump
ã¯éåæã§ãããããããã® pump()
ã®å¼ã³åºãã¯ãããã¹ãã³ãã©ã¼ã®çµããã«ãããããå®éã«ã¯ãããã¹ãã³ãã©ã¼ã®é£éã«é¡ä¼¼ãã¦ãã¾ãã
ã¹ããªã¼ã ã®èªã¿åãã¯ããããã¹ã§ã¯ãªã async/awaitã使ç¨ãã¦æ¸ãã¨ããã«ç°¡åã§ãã
async function readData(url) {
const response = await fetch(url);
const reader = response.body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) {
// ãã¼ã¿ã®æå¾ã®ãã£ã³ã¯ã§ä½ããè¡ãããªã¼ãã¼ãçµäºãã
return;
}
// ããã§ãªãå ´åã¯ãããã§ç¾å¨ã®ãã£ã³ã¯ãå¦çãã
}
}
éåæå復å¦çãç¨ãã fetch() ã®ä½¿ç¨
fetch()
ã使ç¨ããããã«ç°¡åãªæ¹æ³ãããã¾ããããã¯ãfor await...of
æ§æã使ç¨ãã¦ãè¿ããã response.body
ãå復å¦çãããã¨ã§ãã ãã㯠response.body
ã ReadableStream
ãè¿ãããããéåæå復å¯è½ãªã®ã§ãã¾ãåä½ãã¾ãã
ãã®ææ³ãç¨ããã¨ãåç¯ã®ã³ã¼ãä¾ã次ã®ããã«æ¸ãæãããã¨ãã§ãã¾ãã
async function readData(url) {
const response = await fetch(url);
for await (const chunk of response.body) {
// Do something with each "chunk"
}
// Exit when done
}
ã¹ããªã¼ã ã®å復å¦çã䏿¢ãããå ´åã¯ãAbortController
ã¨ããã«é¢é£ä»ãããã AbortSignal
ã使ç¨ã㦠fetch()
å¦çããã£ã³ã»ã«ãããã¨ãã§ãã¾ãï¼
const aborter = new AbortController();
button.addEventListener("click", () => aborter.abort());
logChunks("http://example.com/somefile.txt", { signal: aborter.signal });
async function logChunks(url, { signal }) {
const response = await fetch(url, signal);
for await (const chunk of response.body) {
// ãã£ã³ã¯ã«å¯¾ãã¦ä½ããè¡ã
}
}
ã¾ããä¸è¨ã®ã³ã¼ãã«ç¤ºãããã«ãbreak
ã使ç¨ãã¦ã«ã¼ããçµäºãããã¨ãã§ãã¾ãã ã«ã¼ãå
ã®ã³ã¼ãã¯ãã¹ããªã¼ã ã«æ°ãããã¼ã¿ãæã¤ãã¨ãã§ããã¨ãã«ã®ã¿å®è¡ãããã®ã§ãã·ã°ãã«ã䏿ããã¦ãã break
ãå¼ã³ä»ããããã¾ã§ã«å¤å°ã®é
å»¶ããããã¨ã«æ³¨æãã¦ãã ããã
const aborter = new AbortController();
button.addEventListener("click", () => aborter.abort());
logChunks("http://example.com/somefile.txt", { signal: aborter.signal });
async function logChunks(url, { signal }) {
const response = await fetch(url);
for await (const chunk of response.body) {
if (signal.aborted) break; // ã«ã¼ãããè±åºããã ã
// ãã£ã³ã¯ã«å¯¾ãã¦ä½ããè¡ã
}
}
éåæãªã¼ãã¼ã®ä¾
// A mock push source.
// Used to simulate some random data arriving
class MockPushSource {
// total amount of data to stream from the push source
static #maxData = 90;
// total data read so far (capped to maxData)
#dataRead = 0;
// Method returning promise when this push source is readable.
dataRequest() {
const result = {
bytesRead: 8,
data: "",
};
return new Promise((resolve) => {
if (this.#dataRead >= MockPushSource.#maxData) {
// Out of data
result.bytesRead = 0;
result.data = "";
resolve(result);
return;
}
// Emulate slow read of data
setTimeout(() => {
const numberBytesReceived = 8;
this.#dataRead += numberBytesReceived;
result.data = MockPushSource.#randomChars();
resolve(result);
}, 500);
});
}
// Dummy close function
close() {
return;
}
// Return random character string
static #randomChars(length = 8) {
let string = "";
const choices =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()";
for (let i = 0; i < length; i++) {
string += choices[Math.floor(Math.random() * choices.length)];
}
return string;
}
}
.input {
float: left;
width: 50%;
}
.output {
float: right;
width: 50%;
overflow-wrap: break-word;
}
button {
display: block;
}
<button>Cancel stream</button>
<div class="input">
<h2>Underlying source</h2>
<ul></ul>
</div>
<div class="output">
<h2>Consumer</h2>
<ul></ul>
</div>
// Store reference to lists, paragraph and button
const list1 = document.querySelector(".input ul");
const list2 = document.querySelector(".output ul");
const button = document.querySelector("button");
// Create empty string in which to store final result
let result = "";
// Function to log data from underlying source
function logSource(result) {
const listItem = document.createElement("li");
listItem.textContent = result;
list1.appendChild(listItem);
}
// Function to log data from consumer
function logConsumer(result) {
const listItem = document.createElement("li");
listItem.textContent = result;
list2.appendChild(listItem);
}
const stream = makePushSourceStream();
function makePushSourceStream() {
const pushSource = new MockPushSource();
return new ReadableStream({
start(controller) {
readRepeatedly().catch((e) => controller.error(e));
function readRepeatedly() {
return pushSource.dataRequest().then((result) => {
if (result.data.length == 0) {
logSource(`No data from source: closing`);
controller.close();
return;
}
logSource(`Enqueue data: ${result.data}`);
controller.enqueue(result.data);
return readRepeatedly();
});
}
},
cancel() {
logSource(`cancel() called on underlying source`);
pushSource.close();
},
});
}
// Monkey patch fetch() so it returns a response that is a mocked stream
window.fetch = async (...args) => {
return { body: stream };
};
ä¸è¨ã®ã³ã¼ãã¯ãããå®å
¨ãªä¾ã示ãã¦ãã¾ãã ããã§ã¯ãtry/catch ãããã¯å
ã§å復å¯è½ãªãã¸ã§ã¯ãã使ç¨ãã¦ãã§ããã¹ããªã¼ã ã使ç¨ãã¦ãã¾ãã ã«ã¼ãã®å復å¦çãã¨ã«ãã³ã¼ãã¯åç´ã«åä¿¡ãããã¤ãæ°ããã°åºåãã¦æ°ãã¾ãã ã¨ã©ã¼ãããå ´åã¯ããã®åé¡ããã°åºåãã¾ãã fetch()
å¦ç㯠AbortSignal
ã使ç¨ãã¦åãæ¶ãããå¯è½æ§ãããããã®å ´åãã¨ã©ã¼ã¨ãã¦ãã°åºåããã¾ãã
let bytes = 0;
const aborter = new AbortController();
button.addEventListener("click", () => aborter.abort());
logChunks("http://example.com/somefile.txt", { signal: aborter.signal });
async function logChunks(url, { signal }) {
try {
const response = await fetch(url, signal);
for await (const chunk of response.body) {
if (signal.aborted) throw signal.reason;
bytes += chunk.length;
logConsumer(`Chunk: ${chunk}. Read ${bytes} characters.`);
}
} catch (e) {
if (e instanceof TypeError) {
console.log(e);
logConsumer("TypeError: Browser may not support async iteration");
} else {
logConsumer(`Error in async iterator: ${e}.`);
}
}
}
ä¸è¨ã®ãã°åºåä¾ã§ã¯ãã³ã¼ããå®è¡ããã¦ãããããã©ã¦ã¶ã¼ã ReadableStream
ã®éåæå復å¦çã«å¯¾å¿ãã¦ããªããã¨ã表示ãã¦ãã¾ãã æ£ãã辺ã«ã¯åå¾ãããã£ã³ã¯ã表示ããã¾ãããã§ããã忢ããã«ã¯ãã£ã³ã»ã«ãã¿ã³ãæ¼ãã¾ãã
ã¡ã¢: ãã®ãã§ããå¦çã¯ãã¢ã®ããã«æ¨¡æ¬çã«ä½æããããã®ã§ãã©ã³ãã ã«ããã¹ãã®ãã£ã³ã¯ãçæãã ReadableStream
ãè¿ãã ãã§ãã ä¸è¨å·¦åã®ãåºç¤ã½ã¼ã¹ãã¯æ¨¡æ¬ã½ã¼ã¹ã§çæããããã¼ã¿ã§ãå³åã¯ã³ã³ã·ã¥ã¼ãã¼ããã®ãã°åºåã§ãã ï¼æ¨¡æ¬ã½ã¼ã¹ã®ã³ã¼ãã¯ä¾ã«é¢ä¿ãªãã®ã§è¡¨ç¤ºãã¾ãããï¼
ãã®è¨äºã§å¦ç¿ãã¦ããåç´ãªã¹ããªã¼ã ãã³ãã®ä¾ã«ã¯ 2 çªç®ã®é¨åãå«ã¾ãã¦ãã¾ã â ãã§ããããæ¬ä½ããç»åããã£ã³ã¯åä½ã§èªã¿åã£ãå¾ãç¬èªä½æã®å¥ã®ã«ã¹ã¿ã ã¹ããªã¼ã ã®ãã¥ã¼ã«å
¥ãã¾ãã ãããã©ã®ããã«ä½æããã®ã§ããããï¼ ReadableStream()
ã³ã³ã¹ãã©ã¯ã¿ã¼ã§ãã
Fetch ã®å ´åã®ããã«ããã©ã¦ã¶ã¼ãæä¾ããã¹ããªã¼ã ããèªã¿åãã®ã¯ç°¡åã§ãããæã«ã¯ã«ã¹ã¿ã ã¹ããªã¼ã ã使ããèªåèªèº«ã§ãã£ã³ã¯ãæå
¥ããå¿
è¦ãããå ´åãããã¾ãã ReadableStream()
ã³ã³ã¹ãã©ã¯ã¿ã¼ã使ãã¨ãæåã®ãã¡ã¯è¤éã«è¦ãã¾ãããå®ã¯ããã»ã©æªããªãæ§æã§ãããè¡ããã¨ãã§ãã¾ãã
ä¸è¬çãªæ§æã®éª¨çµã¿ã¯æ¬¡ã®ããã«ãªãã¾ãã
const stream = new ReadableStream(
{
start(controller) {},
pull(controller) {},
cancel() {},
type,
autoAllocateChunkSize,
},
{
highWaterMark: 3,
size: () => 1,
},
);
ã³ã³ã¹ãã©ã¯ã¿ã¼ã¯ã弿°ã¨ã㦠2 ã¤ã®ãªãã¸ã§ã¯ããåãã¾ãã æåã®ãªãã¸ã§ã¯ãã¯å¿ é ã§ããããã¼ã¿ã®èªã¿åãå ã§ããåºã«ãªãã½ã¼ã¹ã®ã¢ãã«ã JavaScript ã§ä½æãã¾ãã 2 çªç®ã®ãªãã¸ã§ã¯ãã¯ãªãã·ã§ã³ã§ãããã¹ããªã¼ã ã«ä½¿ç¨ããã«ã¹ã¿ã ã®ãã¥ã¼ã¤ã³ã°æ¦ç¥ãæå®ã§ãã¾ãã ãããè¡ãå¿ è¦ã¯ã»ã¨ãã©ãªããããããã§ã¯æåã®ãã®ã«éä¸ãã¾ãã
次ã®ããã«æåã®ãªãã¸ã§ã¯ãã«ã¯æå¤§ 5 ã¤ã®ã¡ã³ãã¼ãå«ãããã¨ãã§ããæåã®ãªãã¸ã§ã¯ãã®ã¿ãå¿ é ã§ãã
start(controller)
â ReadableStream
ãæ§ç¯ãããç´å¾ã« 1 åã ãå¼ã³åºãããã¡ã½ããã ãã®ã¡ã½ããå
ã«ã¯ãã¹ããªã¼ã æ©è½ãè¨å®ããã³ã¼ããå«ããå¿
è¦ãããã¾ãã ä¾ãã°ããã¼ã¿ã®çæãéå§ããããã½ã¼ã¹ã«ã¢ã¯ã»ã¹ãã¾ããpull(controller)
â å«ã¾ãã¦ããå ´åãã¹ããªã¼ã ã®å
é¨ãã¥ã¼ããã£ã±ãã«ãªãã¾ã§ç¹°ãè¿ãå¼ã³åºãããã¡ã½ããã ããã¯ãããå¤ãã®ãã£ã³ã¯ããã¥ã¼ã«å
¥ããããã¨ãã«ã¹ããªã¼ã ãå¶å¾¡ããããã«ä½¿ç¨ã§ãã¾ããcancel()
â å«ã¾ãã¦ããå ´åãã¹ããªã¼ã ããã£ã³ã»ã«ãããã¨ãã¢ããªãéç¥ããå ´åã«å¼ã³åºãããã¡ã½ããï¼ä¾ãã°ã ReadableStream.cancel()
ãå¼ã³åºãããå ´åï¼ã å
容ã¯ãã¹ããªã¼ã ã®ã½ã¼ã¹ã¸ã®ã¢ã¯ã»ã¹ãè§£æ¾ããããã«å¿
è¦ãªãã¨ãè¡ãå¿
è¦ãããã¾ããtype
ããã³ autoAllocateChunkSize
â ããããå«ã¾ãã¦ããå ´åãã¹ããªã¼ã ããã¤ãã¹ããªã¼ã ã§ãããã¨ã示ãããã«ä½¿ç¨ããã¾ãã ãã¤ãã¹ããªã¼ã ã¯ãé常ã®ï¼æ¢å®ã®ï¼ã¹ããªã¼ã ã¨ã¯ç¨éã使ç¨ããå ´åãå¤å°ç°ãªããããèªã¿åãå¯è½ãªãã¤ãã¹ããªã¼ã ã®ä½¿ç¨ã§å¥ã«æ±ã£ã¦ãã¾ããç°¡åãªä¾ã®ã³ã¼ããããä¸åº¦è¦ãã¨ã次ã®ããã« ReadableStream()
ã³ã³ã¹ãã©ã¯ã¿ã¼ã«ã¯ããã§ããããã¹ããªã¼ã ãããã¹ã¦ã®ãã¼ã¿ãèªã¿åãããã®åä¸ã®ã¡ã½ãã start()
ã®ã¿ãå«ã¾ãã¦ãããã¨ããããã¾ãã
// å
ã®ç»åããã§ãã
fetch("./tortoise.png")
// æ¬ä½ã ReadableStream ã¨ãã¦åå¾
.then((response) => {
const reader = response.body.getReader();
return new ReadableStream({
start(controller) {
return pump();
function pump() {
return reader.read().then(({ done, value }) => {
// ãã¼ã¿ãæ¶è²»ããå¿
è¦ããªããªã£ãããã¹ããªã¼ã ãéãã¾ã
if (done) {
controller.close();
return;
}
// 次ã®ãã¼ã¿ãã£ã³ã¯ã対象ã®ã¹ããªã¼ã ã®ãã¥ã¼ã«å
¥ãã¾ã
controller.enqueue(value);
return pump();
});
}
},
});
});
ReadableStream ã³ã³ããã¼ã©ã¼
ReadableStream()
ã³ã³ã¹ãã©ã¯ã¿ã¼ã«æ¸¡ããã start()
ã¡ã½ãã㨠pull()
ã¡ã½ããã«ã¯ controller
弿°ãä¸ãããã¾ãã ãããã¯ãã¹ããªã¼ã ã®å¶å¾¡ã«ä½¿ç¨ã§ãã ReadableStreamDefaultController
ã¯ã©ã¹ã®ã¤ã³ã¹ã¿ã³ã¹ã§ãã
ãã®ä¾ã§ã¯ãã³ã³ããã¼ã©ã¼ã® enqueue()
ã¡ã½ããã使ç¨ãã¦ãå¤ããã§ããããæ¬ä½ããèªã¿åã£ãå¾ãã«ã¹ã¿ã ã¹ããªã¼ã ã®ãã¥ã¼ã«å
¥ãã¾ãã
ããã«ããã§ããããæ¬ä½ã®èªã¿åããå®äºããããã³ã³ããã¼ã©ã¼ã® close()
ã¡ã½ããã使ç¨ãã¦ã«ã¹ã¿ã ã¹ããªã¼ã ãéãã¾ãã 以åã«ãã¥ã¼ã«å
¥ãããããã£ã³ã¯ã¯ããããèªã¿åããã¨ãã§ãã¾ããããã¥ã¼ã«å
¥ãããã¨ã¯ã§ãã¾ããã èªã¿åããçµäºããã¨ãã¹ããªã¼ã ã¯éãããã¾ãã
åç´ãªã¹ããªã¼ã ãã³ãã®ä¾ã§ã¯ãã«ã¹ã¿ã ã®èªã¿åãå¯è½ãªã¹ããªã¼ã ã Response
ã³ã³ã¹ãã©ã¯ã¿ã¼ã®å¼ã³åºãã«æ¸¡ããã¨ã§æ¶è²»ãããã®å¾ blob()
ã¨ãã¦æ¶è²»ãã¾ãã
readableStream
.then((stream) => new Response(stream))
.then((response) => response.blob())
.then((blob) => URL.createObjectURL(blob))
.then((url) => console.log((image.src = url)))
.catch((err) => console.error(err));
ãã ããã«ã¹ã¿ã ã¹ããªã¼ã ã ReadableStream
ã¤ã³ã¹ã¿ã³ã¹ã§ãããããããã«ãªã¼ãã¼ãåãã¤ãããã¨ãã§ãã¾ãã ä¾ã¨ãã¦ãåç´ãªã©ã³ãã ã¹ããªã¼ã ï¼Simple random streamï¼ã®ãã¢ãã覧ãã ããï¼ã©ã¤ããåç
§ï¼ãããã¯ã«ã¹ã¿ã ã¹ããªã¼ã ã使ããããã¤ãã®ã©ã³ãã ãªæååããã¥ã¼ã«å
¥ãã¦ããã[æååã®çæã忢] ãã¿ã³ãæ¼ãããã¨ã¹ããªã¼ã ãããã¼ã¿ãå度èªã¿åãã¾ãã
ã¡ã¢: FetchEvent.respondWith()
ã使ç¨ãã¦ã¹ããªã¼ã ãæ¶è²»ããããã«ã¯ããã¥ã¼ã«å
¥ã£ãã¹ããªã¼ã ã³ã³ãã³ã㯠Uint8Array
åã§ãªããã°ãªãã¾ãããä¾ãã°ã TextEncoder
ã使ç¨ãã¦ã¨ã³ã³ã¼ãããã¾ãã
ã«ã¹ã¿ã ã¹ããªã¼ã ã®ã³ã³ã¹ãã©ã¯ã¿ã¼ã«ã¯ãsetInterval()
å¼ã³åºãã使ç¨ã㦠1 ç§ãã¨ã«ã©ã³ãã ãªæååãçæãã start()
ã¡ã½ãããããã¾ãã æ¬¡ã«ãReadableStreamDefaultController.enqueue()
ã使ç¨ãã¦ã¹ããªã¼ã ã«å
¥ãã¾ãã ãã¿ã³ãæ¼ãããã¨ãã¤ã³ã¿ã¼ãã«ããã£ã³ã»ã«ããã readStream()
ã¨å¼ã°ãã颿°ãå¼ã³åºããã¦ããã¼ã¿ãã¹ããªã¼ã ããå度èªã¿åãã¾ãã ã¾ãããã£ã³ã¯ãã¹ããªã¼ã ã®ãã¥ã¼ã¸å
¥ãããã¨ãæ¢ãããããã¹ããªã¼ã ãéãã¾ãã
let interval;
const stream = new ReadableStream({
start(controller) {
interval = setInterval(() => {
const string = randomChars();
// ã¹ããªã¼ã ã«æååã追å
controller.enqueue(string);
// ãããç»é¢ã«è¡¨ç¤º
const listItem = document.createElement("li");
listItem.textContent = string;
list1.appendChild(listItem);
}, 1000);
button.addEventListener("click", () => {
clearInterval(interval);
readStream();
controller.close();
});
},
pull(controller) {
// ãã®ä¾ã§ã¯å®éã«ã¯ pull ã¯å¿
è¦ããã¾ãã
},
cancel() {
// ãªã¼ãã¼ããã£ã³ã»ã«ãããå ´åã«å¼ã³åºãããããã
// æååã®çæã忢ããå¿
è¦ãããã¾ã
clearInterval(interval);
},
});
readStream()
颿°èªä½ã§ã¯ããReadableStream.getReader()
ã使ç¨ãã¦ãªã¼ãã¼ãã¹ããªã¼ã ã«ããã¯ããå
ã»ã©è¦ãã®ã¨åæ§ã®ãã¿ã¼ã³ã«å¾ãã¾ãã read()
ã§åãã£ã³ã¯ãèªã¿åããdone
ã true
ã§ãããã©ããã確èªãããã®å ´åã¯ããã»ã¹ãçµäºããããã§ãªãå ´å㯠read()
ã¡ã½ãããå度å®è¡ããåã«æ¬¡ã®ãã£ã³ã¯ãèªã¿åã£ã¦å¦çãã¾ãã
function readStream() {
const reader = stream.getReader();
let charsReceived = 0;
let result = "";
// read() ã¯ãå¤ãåãåã£ãã¨ãã«è§£æ±ºãããããã¹ãè¿ãã¾ã
reader.read().then(function processText({ done, value }) {
// çµæãªãã¸ã§ã¯ãã«ã¯2ã¤ã®ããããã£ãå«ã¾ãã¾ãã
// done - ã¹ããªã¼ã ããã¹ã¦ã®ãã¼ã¿ãæ¢ã«æä¾ãã¦ããå ´å㯠trueã
// value - ä¸é¨ã®ãã¼ã¿ã done ã true ã®å ´åã常㫠undefinedã
if (done) {
console.log("Stream complete");
para.textContent = result;
return;
}
charsReceived += value.length;
const chunk = value;
const listItem = document.createElement("li");
listItem.textContent = `Read ${charsReceived} characters so far. Current chunk = ${chunk}`;
list2.appendChild(listItem);
result += chunk;
// ããã«èªã¿ããã®é¢æ°ãå度å¼ã³åºãã¾ã
return reader.read().then(processText);
});
}
ã¹ããªã¼ã ã®ã¯ãã¼ãºã¨ãã£ã³ã»ã«
ReadableStreamDefaultController.close()
ã使ç¨ãã¦ãªã¼ãã¼ãéããä¾ãæ¢ã«ç¤ºãã¾ããã åã«è¨ã£ãããã«ã以åã«ãã¥ã¼ã«å
¥ãããããã£ã³ã¯ã¯ãã¹ã¦èªã¿è¾¼ã¾ãã¾ãããéãããã¦ããããããã以ä¸ãã¥ã¼ã«å
¥ãããã¨ã¯ã§ãã¾ããã
ã¹ããªã¼ã ãå®å
¨ã«åãé¤ãããã¥ã¼ã«å
¥ãããããã£ã³ã¯ãç ´æ£ãããå ´åã¯ãReadableStream.cancel()
ã¾ã㯠ReadableStreamDefaultReader.cancel()
ã使ç¨ãã¾ãã
ã¹ããªã¼ã ã 2 ååæã«èªã¿åãããå ´åãããã¾ãã ããã¯ãReadableStream.tee()
ã¡ã½ãããä»ãã¦å®ç¾ããã¾ããå
ã®èªã¿åãå¯è½ãªã¹ããªã¼ã ã® 2 ã¤ã®åä¸ã³ãã¼ãå«ãé
åãåºåãã2 ã¤ã®å¥ã
ã®ãªã¼ãã¼ã§åå¥ã«èªã¿åããã¨ãã§ãã¾ãã
ä¾ãã°ãµã¼ãã¹ã¯ã¼ã«ã¼ã§ããµã¼ãã¼ããã¬ã¹ãã³ã¹ãåå¾ãã¦ãã©ã¦ã¶ã¼ã«ã¹ããªã¼ãã³ã°ãã¤ã¤ããµã¼ãã¹ã¯ã¼ã«ã¼ã®ãã£ãã·ã¥ã«ãã¹ããªã¼ãã³ã°ãããå ´åããã®ãããªãã¨ãè¡ãããããã¾ãããã¬ã¹ãã³ã¹æ¬æã¯è¤æ°åæ¶è²»ãããã¨ãã§ãããã¹ããªã¼ã ã¯ä¸åº¦ã«è¤æ°ã®ãªã¼ãã¼ããèªããªãã®ã§ããããè¡ãã«ã¯ 2 ã¤ã®ã³ãã¼ãå¿ è¦ã§ãã
åç´ãªåå²ã®ä¾ï¼Simple tee exampleï¼ã§ãã®ä¾ã示ãã¾ãï¼ã©ã¤ããåç §ï¼ã ãã®ä¾ã¯ãåç´ãªã©ã³ãã ã¹ããªã¼ã ã¨ã»ã¼åãããã«æ©è½ãã¾ããããã¿ã³ãæ¼ãã¦ã©ã³ãã ãªæååã®çæã忢ããã¨ãã«ã¹ã¿ã ã¹ããªã¼ã ãåå¾ããã¦åå²ãããçµæã®ä¸¡æ¹ã®ã¹ããªã¼ã ãèªã¿åãããç¹ãç°ãªãã¾ãã
function teeStream() {
const teedOff = stream.tee();
readStream(teedOff[0], list2);
readStream(teedOff[1], list3);
}
ãã¤ããã§ã¼ã³
ã¹ããªã¼ã ã®ããä¸ã¤ã®æ©è½ã¨ãã¦ãã¹ããªã¼ã ãäºãã«ãã¤ãæ¥ç¶ããæ©è½ï¼ãã¤ããã§ã¼ã³ã¨å¼ã°ããï¼ãããã¾ãããã®ã¡ã½ããã«ã¯ãèªã¿åãå¯è½ãªã¹ããªã¼ã ãã©ã¤ã¿ã¼ã¨ãªã¼ãã¼ã®ãã¢ãéãã¦ãã¤ãæ¥ç¶ãããããã¼ã¿å½¢å¼ãå¥ã®å½¢å¼ã«å¤æãã ReadableStream.pipeThrough()
ã¨ããã¤ããã§ã¼ã³ã®çµç¹ã¨ãã¦åä½ããã©ã¤ã¿ã¼ã«èªã¿åãå¯è½ãªã¹ããªã¼ã ããã¤ããã ReadableStream.pipeTo()
ã® 2 ã¤ãå«ã¾ãã¾ãã
Unpack Chunks of a PNG (ã©ã¤ãã§ã確èª) ã¨ããç°¡åãªä¾ãè¦ã¦ã¿ã¾ããããããã¯ãç»åãã¹ããªã¼ã ã¨ãã¦åå¾ãããããã«ã¹ã¿ã PNG 夿ã¹ããªã¼ã ã«æ¥ç¶ãã¦ããã¤ããªã¼ãã¼ã¿ã¹ããªã¼ã ãã PNG ãã£ã³ã¯ãåå¾ãããã®ã§ãã
// å
ã®ç»åããã§ãã
fetch("png-logo.png")
// ãã® body ã ReadableStream ã¨ãã¦åå¾
.then((response) => response.body)
// å
ã®ç»åããã°ã¬ã¼ã¹ã±ã¼ã« PNG ã¹ããªã¼ã ã使
.then((rs) => logReadableStream("Fetch Response Stream", rs))
.then((body) => body.pipeThrough(new PNGTransformStream()))
.then((rs) => logReadableStream("PNG Chunk Stream", rs));
TransformStream
ã使ç¨ããä¾ã¯ãã¾ã ããã¾ããã
以ä¸ãããæ¢å®ã®ãèªã¿åãå¯è½ãªã¹ããªã¼ã ã®åºæ¬çãªèª¬æã§ãã
èªã¿åãå¯è½ãªãã¤ãã¹ããªã¼ã ã®ä½¿ç¨æ¹æ³ã«ã¤ãã¦ã¯ãèªã¿åãå¯è½ãªãã¤ãã¹ããªã¼ã ã®ä½¿ç¨ ãåç §ãã¦ãã ãã. ã¹ããªã¼ã ã®å é¨ãã¥ã¼ããã¤ãã¹ãã¦ãã³ã³ã·ã¥ã¼ãã¼ã¸ã®ã¼ãã³ãã¼è»¢éãå¹ççã«å®è¡ã§ããåºç¤ã¨ãªããã¤ãã½ã¼ã¹ã®ããã¹ããªã¼ã ã§ãã
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4