- From: Ardis Lu <notifications@github.com>
- Date: Mon, 28 Apr 2025 00:22:43 -0700
- To: whatwg/streams <streams@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/streams/issues/1344@github.com>
ardislu created an issue (whatwg/streams#1344) ### What is the issue with the Streams Standard? If `cancel` is called immediately after a new `ReadableStream` is instantiated, the logic in `start` may not be completed before `cancel` executes. For example: ```javascript function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } const r = new ReadableStream({ async start() { await sleep(1000); console.log('start completed'); }, cancel() { console.log('cancel completed'); } }); await r.cancel(); // cancel completed // start completed ``` As I understand it, this behavior is by design. However, it may be confusing because `close` and `abort` on `WritableStream` *do* wait for `start` to complete: ```javascript const w = new WritableStream({ async start() { await sleep(1000); console.log('start completed'); }, close() { console.log('close completed'); } }); await w.close(); // start completed // close completed const w2 = new WritableStream({ async start() { await sleep(1000); console.log('start completed'); }, abort() { console.log('abort completed'); } }); await w2.abort(); // start completed // abort completed ``` **In particular**, examples [10.4](https://streams.spec.whatwg.org/#example-rs-pull) and [10.5](https://streams.spec.whatwg.org/#example-rbs-pull) on the standard imply that `cancel` waits for `start` to finish before executing because there is no check that `fs.open` has completed before trying to call `fileHandle.close`: ```javascript const fs = require("fs").promises; function makeReadableFileStream(filename) { let fileHandle; return new ReadableStream({ async start() { fileHandle = await fs.open(filename, "r"); }, // ... cancel() { return fileHandle.close(); // Dangerous: fileHandle may still be undefined } }); } ``` It would be useful if examples 10.4 and 10.5 made an explicit note about this behavior. The example code can also be updated to block `cancel` until `start` is completed. For example: ```diff const fs = require("fs").promises; function makeReadableFileStream(filename) { let fileHandle; + const { promise, resolve } = Promise.withResolvers(); return new ReadableStream({ async start() { fileHandle = await fs.open(filename, "r"); + resolve(); }, // ... - cancel() { + async cancel() { + await promise; return fileHandle.close(); } }); } ``` -- Reply to this email directly or view it on GitHub: https://github.com/whatwg/streams/issues/1344 You are receiving this because you are subscribed to this thread. Message ID: <whatwg/streams/issues/1344@github.com>
Received on Monday, 28 April 2025 07:22:47 UTC