Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Streams APIをちゃんと理解する
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
kato takeshi
November 30, 2019
Programming
3.5k
4
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Streams APIをちゃんと理解する
JSConf JP 2019のセッションでお話しした内容です。
https://jsconf.jp/2019/talk/takeshi-kato
kato takeshi
November 30, 2019
Other Decks in Programming
See All in Programming
モジュールの視点からSwiftを読み解く #iosdc
s_shimotori
0
180
TiDB Cloudのカスタムコントローラーによるオートスケール対応
takaidohigasi
0
120
Heart of Swift Concurrency
koher
0
890
『寄り添うラジオ』をAIで作る 体験価値から逆算した、会話しないUXと品質設計
theoriatec2024
3
180
C#の現在地 進化の歴史と、AI時代の.NET Everywhere
neuecc
4
2.1k
MVNOの申込からeSIM開通までをiOSアプリでつなぐ- 本人確認・MNP・通信事業者基盤をまたぐ実装
satotakeshi
0
420
AI × TiDD / 2026.09.05 Redmine 大阪
tokudiro
1
170
Omarchy Tokyo やると聞いて UMPC 買ってセットアップしてきた
mtsmfm
0
140
選挙速報を多くのユーザーへ 届ける Live Activities 設計
hamayokokuririn
0
140
モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった ? / is-the-business-domain-the-real-complexity
hatsu38
0
310
AIエージェント時代のコードレビューを設計する
nogu66
6
2.7k
AI に Inclusive UI を書かせよう — Design Rules Skill で Compose UI を作り直す
theoriatec2024
1
490
Featured
See All Featured
The Mindset for Success: Future Career Progression
greggifford
PRO
0
500
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
430
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
6.2k
Designing for humans not robots
tammielis
254
26k
[RailsConf 2023] Rails as a piece of cake
palkan
59
7k
BBQ
matthewcrist
89
10k
Google's AI Overviews - The New Search
badams
0
1.6k
Are puppies a ranking factor?
jonoalderson
2
3.9k
Joys of Absence: A Defence of Solitary Play
codingconduct
1
520
Practical Orchestrator
shlominoach
192
12k
Optimizing for Happiness
mojombo
378
71k
WCS-LA-2024
lcolladotor
0
830
Transcript
ʮ4USFBNΛͪΌΜͱཧղ͢Δʯ
4BVOB4QB)FBMUI"EWJTFS⽂ Takeshi Kato Frontend Developer in
ʮ4USFBNΛ੍͢Δͷɺ/PEFKTΛ੍͢ʯ IUUQKYDLIBUFOBCMPHDPNFOUSZ
ʮ4USFBNT"1*ʯ TJODF0DU 4USFBNT8)"58( "QQMF (PPHMF .P[JMMB .JDSPTPGU -JDFOTFEVOEFS$$#:
ʮ4USFBNT"1*ʯ TJODF0DU
4USFBNʁ ετϦʔϜʢӳTUSFBNʣͱɺ ࿈ଓͨ͠σʔλΛʮྲྀΕΔͷʯͱͯ͠ଊ͑ɺ ͦͷσʔλͷೖग़ྗ͋Δ͍ૹड৴Λѻ͏͜ͱͰ͋Γɺ ·ͨͦͷૢ࡞ͷͨΊͷநσʔλܕΛࢦ͢ɻ ग़యϑϦʔඦՊࣄయʰΟΩϖσΟΞʢ8JLJQFEJBʣʱ
αʔό ॲཧ ඳը αʔό ॲཧ ඳը XJUI4USFBN XJUIPVU4USFBN
αʔό αʔό XJUI4USFBN XJUIPVU4USFBN ॲཧ ඳը ॲཧ ඳը
3FBEBCMF 4USFBN 5SBOTGPSN 4USFBN 8SJUBCMF 4USFBN ʮ4USFBNT"1*ʯ
5SBOTGPSN 4USFBN 8SJUBCMF 4USFBN 3FBEBCMF 4USFBN
3FBEBCMF4USFBNʢಡΈࠐΈՄೳͳετϦʔϜʣ 2VF $IVOL 6OEFSMZJOH4PVSDF %BUB ɾ6OEFSMZJOH4PVSDF ɹσʔλͷݯͱͳΔΦϒδΣΫτɻը૾ಈըͳͲͷϝσΟΞ͚ͩͰͳ͘ ɹςΩετɺͳͲѻ͑Δɻ ɾ\3FBEBCMF4USFBN%FGBVMU$POUSPMMFS^ ɹετϦʔϜͷঢ়ଶ෦Ωϡʔͷ੍ޚͳͲΛߦ͏Ϋϥεɻᶃͷૢ࡞Λ୲͢Δɻ
ɾ\3FBEBCMF4USFBN%FGBVMU3FBEFS^ ɹετϦʔϜ͔ΒνϟϯΫΛಡΈऔΔΫϥεɻᶄͷૢ࡞Λ୲͢Δɻ ᶃ ᶄ
const stream = new ReadableStream( { // ͜ͷΦϒδΣΫτ͕Underlying Source start(controller)
{ // ReadableStreamDefaultController controller.enqueue(chunk); // QueʹChunkΛొ͢Δ }, pull(controller) {}, cancel(reason) {} } ); const reader = stream.getReader(); // ReadableStreamDefaultReader reader.read().then(function readProcess({done, value}) { if (done) { return; } result += value; reader.read().then(readProcess); });
const stream = new ReadableStream( { // ͜ͷΦϒδΣΫτ͕Underlying Source start(controller)
{ // ReadableStreamDefaultController controller.enqueue(chunk); // QueʹChunkΛొ͢Δ }, pull(controller) {}, cancel(reason) {} } ); const reader = stream.getReader(); // ReadableStreamDefaultReader reader.read().then(function readProcess({done, value}) { if (done) { return; } result += value; reader.read().then(readProcess); });
const stream = new ReadableStream( { // ͜ͷΦϒδΣΫτ͕Underlying Source start(controller)
{ // ReadableStreamDefaultController controller.enqueue(chunk); // QueʹChunkΛొ͢Δ }, pull(controller) {}, cancel(reason) {} } ); const reader = stream.getReader(); // ReadableStreamDefaultReader reader.read().then(function readProcess({done, value}) { if (done) { return; } result += value; reader.read().then(readProcess); });
const stream = new ReadableStream( { // ͜ͷΦϒδΣΫτ͕Underlying Source start(controller)
{ // ReadableStreamDefaultController controller.enqueue(chunk); // QueʹChunkΛొ͢Δ }, pull(controller) {}, cancel(reason) {} } ); const reader = stream.getReader(); // ReadableStreamDefaultReader reader.read().then(function readProcess({done, value}) { if (done) { return; } result += value; reader.read().then(readProcess); });
$BTFʮ4USFBNJOH3FTQPOTFʯ
'FUDI"1*࣮ߦޙʹड͚औΕΔ3FTQPOTFͷ#PEZ ʮ3FBEBCMF4USFBNʯ ``` fetch(url).then(response => response.body).then(readableStream => { // do
something }); ```
4FSWJDF8PSLFSͰϦΫΤετΛΠϯλʔηϓτͯ͠ɺ 4USFBNΛ3FTQPOTFͱͯ͠ฦ͢
4BNQMF
self.addEventListener('fetch', event => { var stream = new ReadableStream({ async
start(controller) { let html = await caches.match(‘cache.html').then(res => res.text()); const encoder = new TextEncoder(); let pos = 0, chunkSize = 1; function push() { if (pos >= html.length) { controller.close(); return; } controller.enqueue(encoder.encode(html.slice(pos, pos + chunkSize))); pos += chunkSize; setTimeout(push, 5); } push(); } }); event.respondWith(new Response(stream, { headers: {'Content-Type': ‘text/html'} })); }); ࢀߟ: https://jakearchibald.com/2016/streams-ftw/#creating-one-stream-from-multiple-sources-to-supercharge-page-render-times
self.addEventListener('fetch', event => { var stream = new ReadableStream({ async
start(controller) { let html = await caches.match(‘cache.html').then(res => res.text()); const encoder = new TextEncoder(); let pos = 0, chunkSize = 1; function push() { if (pos >= html.length) { controller.close(); return; } controller.enqueue(encoder.encode(html.slice(pos, pos + chunkSize))); pos += chunkSize; setTimeout(push, 5); } push(); } }); event.respondWith(new Response(stream, { headers: {'Content-Type': ‘text/html'} })); }); ࢀߟ: https://jakearchibald.com/2016/streams-ftw/#creating-one-stream-from-multiple-sources-to-supercharge-page-render-times
self.addEventListener('fetch', event => { var stream = new ReadableStream({ async
start(controller) { let html = await caches.match(‘cache.html').then(res => res.text()); const encoder = new TextEncoder(); let pos = 0, chunkSize = 1; function push() { if (pos >= html.length) { controller.close(); return; } controller.enqueue(encoder.encode(html.slice(pos, pos + chunkSize))); pos += chunkSize; setTimeout(push, 5); } push(); } }); event.respondWith(new Response(stream, { headers: {'Content-Type': ‘text/html'} })); }); ࢀߟ: https://jakearchibald.com/2016/streams-ftw/#creating-one-stream-from-multiple-sources-to-supercharge-page-render-times event.respondWith(new Response(stream, { headers: {'Content-Type': ‘text/html’} }));
``` caches.match(request).then(res => res.body).then(readableStream => { // do something });
``` $BDIF"1*࣮ߦޙʹड͚औΕΔ3FTQPOTFͷ#PEZ ʮ3FBEBCMF4USFBNʯ
ϔομʔʢDBDIFʣ ίϯςϯπʢGFUDIʣ ϑολʔʢDBDIFʣ ͷΑ͏ͳ͜ͱͰ͖Δ
var stream = new ReadableStream({ start(controller) { const header =
caches.match('./inc/header.html'); const contents = fetch(event.request.url); const footer = caches.match('./inc/footer.html'); function push(stream) { const reader = stream.getReader(); function read({done, value}) { if (done) return; controller.enqueue(value); return reader.read().then(read); } return reader.read().then(read); } header.then(response => push(response.body)).then(() => contents) .then(response => push(response.body)).then(() => footer) .then(response => push(response.body)).then(() => controller.close()); } }); event.respondWith(new Response(stream, { headers: {'Content-Type': ‘text/html'} })); ࢀߟ: https://gist.github.com/jakearchibald/64e26e7a1d9b06b3fa3ec0383f2b1f91
var stream = new ReadableStream({ start(controller) { const header =
caches.match('./inc/header.html'); const contents = fetch(event.request.url); const footer = caches.match('./inc/footer.html'); function push(stream) { const reader = stream.getReader(); function read({done, value}) { if (done) return; controller.enqueue(value); return reader.read().then(read); } return reader.read().then(read); } header.then(response => push(response.body)).then(() => contents) .then(response => push(response.body)).then(() => footer) .then(response => push(response.body)).then(() => controller.close()); } }); event.respondWith(new Response(stream, { headers: {'Content-Type': ‘text/html'} })); ࢀߟ: https://gist.github.com/jakearchibald/64e26e7a1d9b06b3fa3ec0383f2b1f91
var stream = new ReadableStream({ start(controller) { const header =
caches.match('./inc/header.html'); const contents = fetch(event.request.url); const footer = caches.match('./inc/footer.html'); function push(stream) { const reader = stream.getReader(); function read({done, value}) { if (done) return; controller.enqueue(value); return reader.read().then(read); } return reader.read().then(read); } header.then(response => push(response.body)).then(() => contents) .then(response => push(response.body)).then(() => footer) .then(response => push(response.body)).then(() => controller.close()); } }); event.respondWith(new Response(stream, { headers: {'Content-Type': ‘text/html'} })); ࢀߟ: https://gist.github.com/jakearchibald/64e26e7a1d9b06b3fa3ec0383f2b1f91
var stream = new ReadableStream({ start(controller) { const header =
caches.match('./inc/header.html'); const contents = fetch(event.request.url); const footer = caches.match('./inc/footer.html'); function push(stream) { const reader = stream.getReader(); function read({done, value}) { if (done) return; controller.enqueue(value); return reader.read().then(read); } return reader.read().then(read); } header.then(response => push(response.body)).then(() => contents) .then(response => push(response.body)).then(() => footer) .then(response => push(response.body)).then(() => controller.close()); } }); event.respondWith(new Response(stream, { headers: {'Content-Type': ‘text/html'} })); ࢀߟ: https://gist.github.com/jakearchibald/64e26e7a1d9b06b3fa3ec0383f2b1f91
3FBEBCMF4USFBNΛ͏ͱ σʔλΛׂͯ͠গͣͭ͠ ಡΈࠐΉ͜ͱ͕Ͱ͖Δ
5SBOTGPSN 4USFBN 3FBEBCMF 4USFBN 8SJUBCMF 4USFBN
8SJUBCMF4USFBNʢॻ͖ࠐΈՄೳͳετϦʔϜʣ 2VF 6OEFSMZJOH4JOL /FX%BUB ɾ\6OEFSMZJOH4JOL^ ɹΩϡʔ͔ΒνϟϯΫΛड͚औͬͯॻ͖ࠐΈΛߦ͏ΦϒδΣΫτɻ ɾ\8SJUBCMF4USFBN%FGBVMU8SJUFS^ ɹ8SJUBCMF4USFBNʹνϟϯΫΛॻ͖ࠐΉ͜ͱ͕Ͱ͖ΔΫϥεɻ ɹᶃͷૢ࡞Λ୲͢Δɻ ɾ\8SJUBCMF4USFBN%FGBVMU$POUSPMMFS^
ɹετϦʔϜͷঢ়ଶ෦Ωϡʔͷ੍ޚͳͲΛߦ͏Ϋϥεɻᶄͷૢ࡞Λ୲͢Δɻ ᶄ ᶃ
const stream = new WritableStream( { // ͜ͷΦϒδΣΫτ͕UnderlyingSink start(controller) {},
write(chunk, controller) { // WritableStreamDefaultController output.value = chunk; // Hello }, close() {}, abort(reason) {} } ); const writer = stream.getWriter(); // WritableStreamDefaultWriter writer.ready.then(() => writer.write('hello')) .then(() => writer.write('world')) .then(() => writer.close()) .then(() => console.log('close writer.'))
const stream = new WritableStream( { // ͜ͷΦϒδΣΫτ͕UnderlyingSink start(controller) {},
write(chunk, controller) { // WritableStreamDefaultController output.value = chunk; // Hello }, close() {}, abort(reason) {} } ); const writer = stream.getWriter(); // WritableStreamDefaultWriter writer.ready.then(() => writer.write('hello')) .then(() => writer.write('world')) .then(() => writer.close()) .then(() => console.log('close writer.'))
const stream = new WritableStream( { // ͜ͷΦϒδΣΫτ͕UnderlyingSink start(controller) {},
write(chunk, controller) { // WritableStreamDefaultController output.value = chunk; // Hello }, close() {}, abort(reason) {} } ); const writer = stream.getWriter(); // WritableStreamDefaultWriter writer.ready.then(() => writer.write('hello')) .then(() => writer.write('world')) .then(() => writer.close()) .then(() => console.log('close writer.'))
const stream = new WritableStream( { // ͜ͷΦϒδΣΫτ͕UnderlyingSink start(controller) {},
write(chunk, controller) { // WritableStreamDefaultController output.value = chunk; // Hello }, close() {}, abort(reason) {} } ); const writer = stream.getWriter(); // WritableStreamDefaultWriter writer.ready.then(() => writer.write('hello')) .then(() => writer.write('world')) .then(() => writer.close()) .then(() => console.log('close writer.'))
3FBEBCMF 4USFBN 8SJUBCMF 4USFBN QJQF5P
$BTFʮ/BUJWF'JMF4ZTUFNʯ ʮϑΝΠϧΛ'FUDIͯ͠ɺυϥΠϒʹॻ͖ࠐΈʯ
4BNQMF
fetch('https://streams.spec.whatwg.org/').then(async (res) => { const readableStream = res.body; const fileWriter
= await handle.createWriter(); // handleNativeFileSystemAPI͔ΒಘͨΦϒδΣΫτ let offset = 0; const writableStream = new WritableStream({ start() { return fileWriter.truncate(0); }, write(chunk, controller) { return new Promise(async (resolve, reject) => { try { await fileWriter.write(offset, chunk); offset += chunk.length; resolve(); } catch(err) { controller.error(err); reject(err); } }); }, close() { fileWriter.close(); } }); readableStream.pipeTo(writableStream); })
fetch('https://streams.spec.whatwg.org/').then(async (res) => { const readableStream = res.body; const fileWriter
= await handle.createWriter(); // handleNativeFileSystemAPI͔ΒಘͨΦϒδΣΫτ let offset = 0; const writableStream = new WritableStream({ start() { return fileWriter.truncate(0); }, write(chunk, controller) { return new Promise(async (resolve, reject) => { try { await fileWriter.write(offset, chunk); offset += chunk.length; resolve(); } catch(err) { controller.error(err); reject(err); } }); }, close() { fileWriter.close(); } }); readableStream.pipeTo(writableStream); })
fetch('https://streams.spec.whatwg.org/').then(async (res) => { const readableStream = res.body; const fileWriter
= await handle.createWriter(); // handleNativeFileSystemAPI͔ΒಘͨΦϒδΣΫτ let offset = 0; const writableStream = new WritableStream({ start() { return fileWriter.truncate(0); }, write(chunk, controller) { return new Promise(async (resolve, reject) => { try { await fileWriter.write(offset, chunk); offset += chunk.length; resolve(); } catch(err) { controller.error(err); reject(err); } }); }, close() { fileWriter.close(); } }); readableStream.pipeTo(writableStream); })
fetch('https://streams.spec.whatwg.org/').then(async (res) => { const readableStream = res.body; const fileWriter
= await handle.createWriter(); // handleNativeFileSystemAPI͔ΒಘͨΦϒδΣΫτ let offset = 0; const writableStream = new WritableStream({ start() { return fileWriter.truncate(0); }, write(chunk, controller) { return new Promise(async (resolve, reject) => { try { await fileWriter.write(offset, chunk); offset += chunk.length; resolve(); } catch(err) { controller.error(err); reject(err); } }); }, close() { fileWriter.close(); } }); readableStream.pipeTo(writableStream); })
/BUJWF'JMF4ZTUFN Y 4USFBNT"1* IUUQTHJUIVCDPNXJDHOBUJWFpMFTZTUFNJTTVFT 4USFBNΛ༻ͨ͠ॻ͖ࠐΈͷ࣮͕ʢଟʣਐΜͰ͍Δ
8SJUBCMF4USFBNΛ͏ͱ ׂ͞ΕͨσʔλΛ Ұͭͣͭɺॱ൪ʹ ॻ͖ࠐΉ͜ͱ͕Ͱ͖Δ
3FBEBCMF 4USFBN 8SJUBCMF 4USFBN 5SBOTGPSN 4USFBN
5SBOTGPSN4USFBNɹʢมετϦʔϜʣ 8SJUBCMF4USFBN 5SBOTGPSNFS 3FBEBCMF4USFBN ɾ\XSJUBCMF SFBEBCMF^ ɹ8SJUBCMF4USFBNͱ3FBEBCMF4USFBNΛแ͍ͯ͠Δɻ ɾ\5SBOTGPSNFS^ ɹ8SJUBCMF4USFBN͔Β$IVOLΛड͚औͬͯɺมॲཧΛߦ͏ΦϒδΣΫτɻ ɾ\5SBOTGPSN4USFBN%FGBVMU$POUSPMMFS^
ɹ8SJUBCMFɺ3FBEBCMF4USFBNͷঢ়ଶΩϡʔͷ੍ޚͳͲΛߦ͏Ϋϥεɻ
const transformStream = new TransformStream( { // ͜ͷΦϒδΣΫτ͕Transformer start(controller) {},
transform(chunk, controller) { // Τϯίʔυ͞ΕͨChunkΛσίʔυͯ͠Ωϡʔʹొ͢Δ controller.enqueue(new TextDecoder().decode(chunk)); }, flush(controller) { // Writable StreamʹΑΔશͯͷॻ͖ࠐΈ͕ऴΘΓɺ // Writable Stream͕Ϋϩʔζ͠Α͏ͱ͍ͯ͠Δ࣌ʹݺͼग़͞ΕΔ } } ); const {readable, writable} = transformStream; writable.getWriter().write( new Uint8Array([104,101,108,108,111,32,119,111,114,108,100]) ); readable.getReader().read().then(({done, value}) => { console.log(value); // Hello World });
const transformStream = new TransformStream( { // ͜ͷΦϒδΣΫτ͕Transformer start(controller) {},
transform(chunk, controller) { // Τϯίʔυ͞ΕͨChunkΛσίʔυͯ͠Ωϡʔʹొ͢Δ controller.enqueue(new TextDecoder().decode(chunk)); }, flush(controller) { // Writable StreamʹΑΔશͯͷॻ͖ࠐΈ͕ऴΘΓɺ // Writable Stream͕Ϋϩʔζ͠Α͏ͱ͍ͯ͠Δ࣌ʹݺͼग़͞ΕΔ } } ); const {readable, writable} = transformStream; writable.getWriter().write( new Uint8Array([104,101,108,108,111,32,119,111,114,108,100]) ); readable.getReader().read().then(({done, value}) => { console.log(value); // Hello World });
const transformStream = new TransformStream( { // ͜ͷΦϒδΣΫτ͕Transformer start(controller) {},
transform(chunk, controller) { // Τϯίʔυ͞ΕͨChunkΛσίʔυͯ͠Ωϡʔʹొ͢Δ controller.enqueue(new TextDecoder().decode(chunk)); }, flush(controller) { // Writable StreamʹΑΔશͯͷॻ͖ࠐΈ͕ऴΘΓɺ // Writable Stream͕Ϋϩʔζ͠Α͏ͱ͍ͯ͠Δ࣌ʹݺͼग़͞ΕΔ } } ); const {readable, writable} = transformStream; writable.getWriter().write( new Uint8Array([104,101,108,108,111,32,119,111,114,108,100]) ); readable.getReader().read().then(({done, value}) => { console.log(value); // Hello World });
const transformStream = new TransformStream( { // ͜ͷΦϒδΣΫτ͕Transformer start(controller) {},
transform(chunk, controller) { // Τϯίʔυ͞ΕͨChunkΛσίʔυͯ͠Ωϡʔʹొ͢Δ controller.enqueue(new TextDecoder().decode(chunk)); }, flush(controller) { // Writable StreamʹΑΔશͯͷॻ͖ࠐΈ͕ऴΘΓɺ // Writable Stream͕Ϋϩʔζ͠Α͏ͱ͍ͯ͠Δ࣌ʹݺͼग़͞ΕΔ } } ); const {readable, writable} = transformStream; writable.getWriter().write( new Uint8Array([104,101,108,108,111,32,119,111,114,108,100]) ); readable.getReader().read().then(({done, value}) => { console.log(value); // Hello World });
const transformStream = new TransformStream( { // ͜ͷΦϒδΣΫτ͕Transformer start(controller) {},
transform(chunk, controller) { // Τϯίʔυ͞ΕͨChunkΛσίʔυͯ͠Ωϡʔʹొ͢Δ controller.enqueue(new TextDecoder().decode(chunk)); }, flush(controller) { // Writable StreamʹΑΔશͯͷॻ͖ࠐΈ͕ऴΘΓɺ // Writable Stream͕Ϋϩʔζ͠Α͏ͱ͍ͯ͠Δ࣌ʹݺͼग़͞ΕΔ } } ); const {readable, writable} = transformStream; writable.getWriter().write( new Uint8Array([104,101,108,108,111,32,119,111,114,108,100]) ); readable.getReader().read().then(({done, value}) => { console.log(value); // Hello World });
3FBEBCMF 4USFBN 5SBOTGPSN 4USFBN 8SJUBCMF 4USFBN QJQF5ISPVHI 3&563/3FBEBCMF4USFBN QJQF5P
3&563/1SPNJTF
5FYU&ODPEFS4USFBNɾ5FYU%FDPEFS4USFBN GSPN&ODPEJOH"1*
const transformStream = new TransformStream( { // ͜ͷΦϒδΣΫτ͕Transformer start(controller) {},
transform(chunk, controller) { // Τϯίʔυ͞ΕͨChunkΛσίʔυͯ͠Ωϡʔʹొ͢Δ controller.enqueue(new TextDecoder().decode(chunk)); }, flush(controller) { // Writable StreamʹΑΔશͯͷॻ͖ࠐΈ͕ऴΘΓɺ // Writable Stream͕Ϋϩʔζ͠Α͏ͱ͍ͯ͠Δ࣌ʹݺͼग़͞ΕΔ } } ); const {readable, writable} = transformStream; writable.getWriter().write( new Uint8Array([104,101,108,108,111,32,119,111,114,108,100]) ); readable.getReader().read().then(({done, value}) => { console.log(value); // Hello World });
const textDecoderStream = new TextDecoderStream('utf-8'); const {readable, writable} = textDecoderStream;
writable.getWriter().write( new Uint8Array([104,101,108,108,111,32,119,111,114,108,100]) ); readable.getReader().read().then(({done, value}) => { console.log(value); // Hello World }); ˞ͨͩ͠ɺ5SBOTGFS4USFBNͷܧঝͰͳ͍ɻʢಉ͡*'Λඋ͍͑ͯΔ͚ͩʣ ࢀߟIUUQTHJUIVCDPNXIBUXHFODPEJOHJTTVFT
$BTFʮ༁ʯ
4BNQMF
function md2HTMLFactory() { return new TransformStream({ transform(chunk, controller) { controller.enqueue(marked(chunk));
} }); } const translateStream = new TransformStream({ transform(chunk, controller) { return fetch(`https://translation.googleapis.com/language/translate/v2/?key={API_KEY}`, { method: 'POST', body: JSON.stringify({ q: chunk, target: 'en', format: 'html' }) }).then(res => res.json()).then(res => { controller.enqueue(res.data.translations[0].translatedText); }); } }); input.addEventListener('change', function () { const stream = input.files[0].stream(); const [org, willBeTranslated] = stream.tee(); Promise.all([ org.pipeThrough(new TextDecoderStream('utf-8')).pipeThrough(md2HTMLFactory()) .pipeTo(originalWriter), willBeTranslated.pipeThrough(new TextDecoderStream('utf-8')).pipeThrough(md2HTMLFactory()) .pipeThrough(translateStream) .pipeTo(translatedWriter) ]).then(() => console.log('complete')); });
function md2HTMLFactory() { return new TransformStream({ transform(chunk, controller) { controller.enqueue(marked(chunk));
} }); } const translateStream = new TransformStream({ transform(chunk, controller) { return fetch(`https://translation.googleapis.com/language/translate/v2/?key={API_KEY}`, { method: 'POST', body: JSON.stringify({ q: chunk, target: 'en', format: 'html' }) }).then(res => res.json()).then(res => { controller.enqueue(res.data.translations[0].translatedText); }); } }); input.addEventListener('change', function () { const stream = input.files[0].stream(); const [org, willBeTranslated] = stream.tee(); Promise.all([ org.pipeThrough(new TextDecoderStream('utf-8')).pipeThrough(md2HTMLFactory()) .pipeTo(originalWriter), willBeTranslated.pipeThrough(new TextDecoderStream('utf-8')).pipeThrough(md2HTMLFactory()) .pipeThrough(translateStream) .pipeTo(translatedWriter) ]).then(() => console.log('complete')); }); function md2HTMLFactory() { return new TransformStream({ transform(chunk, controller) { controller.enqueue(marked(chunk)); } }); }
function md2HTMLFactory() { return new TransformStream({ transform(chunk, controller) { controller.enqueue(marked(chunk));
} }); } const translateStream = new TransformStream({ transform(chunk, controller) { return fetch(`https://translation.googleapis.com/language/translate/v2/?key={API_KEY}`, { method: 'POST', body: JSON.stringify({ q: chunk, target: 'en', format: 'html' }) }).then(res => res.json()).then(res => { controller.enqueue(res.data.translations[0].translatedText); }); } }); input.addEventListener('change', function () { const stream = input.files[0].stream(); const [org, willBeTranslated] = stream.tee(); Promise.all([ org.pipeThrough(new TextDecoderStream('utf-8')).pipeThrough(md2HTMLFactory()) .pipeTo(originalWriter), willBeTranslated.pipeThrough(new TextDecoderStream('utf-8')).pipeThrough(md2HTMLFactory()) .pipeThrough(translateStream) .pipeTo(translatedWriter) ]).then(() => console.log('complete')); }); const translateStream = new TransformStream({ transform(chunk, controller) { return fetch(`https://translation.googleapis.com/language/translate/v2/?key={API_KEY}`, { method: 'POST', body: JSON.stringify({ q: chunk, target: 'en', format: 'html' }) }).then(res => res.json()).then(res => { controller.enqueue(res.data.translations[0].translatedText); }); } });
function md2HTMLFactory() { return new TransformStream({ transform(chunk, controller) { controller.enqueue(marked(chunk));
} }); } const translateStream = new TransformStream({ transform(chunk, controller) { return fetch(`https://translation.googleapis.com/language/translate/v2/?key={API_KEY}`, { method: 'POST', body: JSON.stringify({ q: chunk, target: 'en', format: 'html' }) }).then(res => res.json()).then(res => { controller.enqueue(res.data.translations[0].translatedText); }); } }); input.addEventListener('change', function () { const stream = input.files[0].stream(); const [org, willBeTranslated] = stream.tee(); Promise.all([ org.pipeThrough(new TextDecoderStream('utf-8')).pipeThrough(md2HTMLFactory()) .pipeTo(originalWriter), willBeTranslated.pipeThrough(new TextDecoderStream('utf-8')).pipeThrough(md2HTMLFactory()) .pipeThrough(translateStream) .pipeTo(translatedWriter) ]).then(() => console.log('complete')); }); input.addEventListener('change', function () { // input[type=“file”]ͷinputཁૉ const stream = input.files[0].stream(); // fileΦϒδΣΫτstream()ͰReadableStream͕औಘͰ͖Δ const [org, willBeTranslated] = stream.tee(); Promise.all([ org.pipeThrough(new TextDecoderStream(‘utf-8')) .pipeThrough(md2HTMLFactory()) .pipeTo(originalWriter), willBeTranslated.pipeThrough(new TextDecoderStream(‘utf-8')) .pipeThrough(md2HTMLFactory()) .pipeThrough(translateStream) .pipeTo(translatedWriter) ]).then(() => console.log('complete')); });
function md2HTMLFactory() { return new TransformStream({ transform(chunk, controller) { controller.enqueue(marked(chunk));
} }); } const translateStream = new TransformStream({ transform(chunk, controller) { return fetch(`https://translation.googleapis.com/language/translate/v2/?key={API_KEY}`, { method: 'POST', body: JSON.stringify({ q: chunk, target: 'en', format: 'html' }) }).then(res => res.json()).then(res => { controller.enqueue(res.data.translations[0].translatedText); }); } }); input.addEventListener('change', function () { const stream = input.files[0].stream(); const [org, willBeTranslated] = stream.tee(); Promise.all([ org.pipeThrough(new TextDecoderStream('utf-8')).pipeThrough(md2HTMLFactory()) .pipeTo(originalWriter), willBeTranslated.pipeThrough(new TextDecoderStream('utf-8')).pipeThrough(md2HTMLFactory()) .pipeThrough(translateStream) .pipeTo(translatedWriter) ]).then(() => console.log('complete')); }); input.addEventListener('change', function () { // input[type=“file”]ͷinputཁૉ const stream = input.files[0].stream(); // fileΦϒδΣΫτstream()ͰReadableStream͕औಘͰ͖Δ const [org, willBeTranslated] = stream.tee(); Promise.all([ org.pipeThrough(new TextDecoderStream(‘utf-8')) .pipeThrough(md2HTMLFactory()) .pipeTo(originalWriter), willBeTranslated.pipeThrough(new TextDecoderStream(‘utf-8')) .pipeThrough(md2HTMLFactory()) .pipeThrough(translateStream) .pipeTo(translatedWriter) ]).then(() => console.log('complete')); });
3FBEBCMF4USFBNɾ8SJUBCMF4USFBNΛར༻͢ΔΞΫςΟϒͳಡΈऔ Γػͱॻ͖ࠐΈػ͕͋Δؒɺ֤ετϦʔϜʮϩοΫʯ͞Εɺղ์͞ΕΔ ·Ͱଞ͔ΒετϦʔϜར༻Ͱ͖ͳ͘ͳΔɻ const readable = new ReadableStream(); const writable
= new WritableStream(); const reader = readable.getReader(); const writer = writable.getWriter(); console.log(readable.locked); // true console.log(writable.locked); // true readable.getReader(); // error! MPDLFEͱUFF
ಉ͡3FBEBCMFετϦʔϜΛ͍͍ͨ߹ೋຢԽʢUFFʣ͢Δඞཁ͕͋ Γ·͢ɻ ྫʣJOQVU<UZQFlpMFz>ͰΞοϓϩʔυͨ͠ϑΝΠϧΛTUSFBNͰѻ͏ྫ MPDLFEͱUFF input.addEventListener('change', function () { const stream
= input.files[0].stream(); // ͓͓ͱΛڞ༗ͨ͠2ͭͷStreamͷྻ͕ಘΒΕΔ const [org, translated] = stream.tee(); … });
5SBOTGPSN4USFBNΛ͏ͱ νϟϯΫΛྲྀΕΔΑ͏ʹม͠ɺ ͞ΒʹಡΈࠐΈ͢͜ͱ͕Ͱ͖Δ
3FBEBCMF 4USFBN 8SJUBCMF 4USFBN 5SBOTGPSN 4USFBN
ͦͷଞͷ֓೦ͱ"1* ɾഎѹʢ#BDL1SFTTVSFʣ ɾ1VTI4PVSDFͱ1VMM4PVSDF ɾ2VFVJOH4USBUFHZ
3FBEBCMF 4USFBN 8SJUBCMF 4USFBN #BDL1SFTTVSFͱ ޙΖ͕٧·ͬͨʢΩϡʔʹۭ͖͕ͳ͘ͳͬͨʣ࣌ʹɺ
8SJUBCMF 4USFBN 3FBEBCMF 4USFBN #BDL1SFTTVSFͱ ޙΖ͕٧·ͬͨʢΩϡʔʹۭ͖͕ͳ͘ͳͬͨʣ࣌ʹɺ ύΠϓΛ௨ͯ͠લͷετϦʔϜʹ௨͢Δ
ɾ1VTI4PVSDF ɹ4PVSDFଆ͔ΒࣗൃతʹFORVFVF͢ΔλΠϓ FH4PDLFU ɾ1VMM4PVSDF ɹϦΫΤετʹԠͯ͡FORVFVF͢ΔλΠϓ FHϑΝΠϧϋϯυϧ ɹ 6OEFSMZJOH4PVSDFͷͭͷλΠϓ
1VTI4PVSDF new ReadableStream({ start(controller) { socket.addEventListener('message', (e) => { controller.enqueue(e.data);
}); } }); 1VMM4PVSDF new ReadableStream({ pull(controller) { controller.enqueue(Math.random()); } }); ˞TUBSUΛ͍ͬͯΕ1VTIɺQVMMΛ͍ͬͯΕ1VMMͱ͍͏Θ͚Ͱ͋Γ·ͤΜɻ
1VTI4PVSDF new ReadableStream({ start(controller) { socket.addEventListener('message', (e) => { controller.enqueue(e.data);
}); } }); 1VMM4PVSDF new ReadableStream({ pull(controller) { controller.enqueue(Math.random()); } }); QVMMϝιου Ωϡʔʹۭ͖͕ͳ͘ͳΔ·Ͱ ࣮ߦ͞ΕΔ
1VTI4PVSDF new ReadableStream({ start(controller) { socket.addEventListener('message', (e) => { controller.enqueue(e.data);
}); } }); 1VMM4PVSDF new ReadableStream({ pull(controller) { controller.enqueue(Math.random()); } }); QVMMϝιου Ωϡʔʹۭ͖ʢʁʣ͕ͳ͘ͳΔ·Ͱ ࣮ߦ͞ΕΔ
֤ετϦʔϜ͕࣋ͭΩϡʔʹอ࣋Ͱ͖ΔαΠζͱ࠷େʢͭ·Γۭ͖ʣΛ ܾΊΔΦϒδΣΫτɻΦϒδΣΫτҎԼͷϓϩύςΟΛ࣋ͭɻ ɾIJHI8BUFS.BSLOVNCFS ɹετϦʔϜͷݶքਫҐʢΩϟύγςΟʣΛࢦఆ͢Δɻɹ )8.ʢΩϡʔʹొ͞Ε͍ͯΔνϟϯΫͷ߹ܭαΠζʣ ɾTJ[F DIVOL OVNCFS ɹԿΛͬͯΩϡʔͷαΠζΛදݱ͢Δ͔Λܾఆ͢Δؔɻ 2VFVJOH4USBUFHZ
ྫʣDIVOLΛจࣈྻͱͯ͠ड͚औΔ͜ͱΛఆͨ͠߹ɺ ɹ͜ͷ4USFBN߹ܭจࣈ·Ͱ͔͠Ωϡʔʹొ͢Δ͜ͱ͕Ͱ͖ͳ͍ɻ new ReadableStream({ pull(controller) { controller.enqueue('pull'); } },{ size(chunk)
{ return chunk.length; }, highWaterMark: 100 }); 2VFVJOH4USBUFHZ
ʮ4USFBNT"1*ʯ TJODF0DU 4USFBNT8)"58( "QQMF (PPHMF .P[JMMB .JDSPTPGU -JDFOTFEVOEFS$$#:
4USFBNTʢͱͦͷपลʣͷࠓޙ
(JTDPNJOHUP+BQBOJO ɾߴɺେ༰ྔ ɾԆ ɾଟଓ
ωοτϫʔΫʹؔ͢ΔύϑΥʔϚϯεվળࡦ ɾͰ͖Δ͚ͩϦΫΤετϑΝΠϧαΠζΛݮΒ͢ ɹɾεϓϥΠτը૾Λ͏ ɹɾςΩετϑΝΠϧΛѹॖ͢Δ ɾQSFMPBE QSFGFUDI ɾΩϟογϡɺ$%/ͷར༻ ͜Ε·ͰϘτϧωοΫͱ͞Ε͖ͯͨͷ͕(ʹΑͬͯ վળ͞ΕΔɻ
ʮ(ͩ͠ɺϑΝΠϧαΠζͳΜͯؔͳ͍ΑͶ ʯ େ༰ྔͷϑΝΠϧ͕৴͞Εɺ ΫϥΠΞϯτͷॲཧ͕͍͔ͭͳ͘ͳΔ͔ʜʁ ʮΫϥυήʔϛϯάαʔϏε࢝Ί͍ͨʂʯ ʮϥΠϒετϦʔϛϯάͰ৴͍ͨ͠ʂʯ
ʮ8FC$PEFDTʯ ϒϥβ͕උ͑ΔίʔσοΫίϯςφΛར༻͢ΔͨΊͷ"1*
ɾ4USFBNT-JWJOH4UBOEBSEຊޠ༁ IUUQTUSJQMFVOEFSTDPSFHJUIVCJP4USFBNTKBIUNM ɾTUSFBNCFUXFFOOPEFKTBOEXIBUXH IUUQTTQFBLFSEFDLDPNKYDLTUSFBNCFUXFFOOPEFKTBOEXIBUXH ɾ4USFBN:PVS8BZUP*NNFEJBUF3FTQPOTFT
IUUQTEFWFMPQFSTHPPHMFDPNXFCVQEBUFTTX SFBEBCMFTUSFBNT ɾࠓͷίʔυαϯϓϧͳͲ IUUQTHJUIVCDPNULTLUPTUSFBNFYBNQMFT ࢀߟࢿྉ
5IBOLZPV