-
Notifications
You must be signed in to change notification settings - Fork 165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Promises based transform() #185
Comments
there is precedence with node.js streams where values can either be passes to push (enqueue) or to the callback, in practice this works pretty well for the large percentage of the time where you are only transforming one thing. |
@calvinmetcalf that is not what I am seeing with http://nodejs.org/docs/latest/api/stream.html#stream_transform_transform_chunk_encoding_callback ? |
That is how it works, though it isn't actually documented, (writing pull request for the documentation now) |
Consider the example at https://streams.spec.whatwg.org/#example-rs-pull, in particular: pull(enqueue, close, error) {
const buffer = new ArrayBuffer(CHUNK_SIZE);
fs.read(fd, buffer, 0, CHUNK_SIZE, position).then(bytesRead => {
if (bytesRead === 0) {
return fs.close(fd).then(close);
} else {
position += bytesRead;
enqueue(buffer);
}
})
.catch(error);
}, with promises, this would become pull(enqueue, close) {
const buffer = new ArrayBuffer(CHUNK_SIZE);
return fs.read(fd, buffer, 0, CHUNK_SIZE, position).then(bytesRead => {
if (bytesRead === 0) {
return fs.close(fd).then(close);
} else {
position += bytesRead;
enqueue(buffer);
}
});
}, That is, it allows you to return a promise for error propagation. That's kind of nice. Not revolutionary. And I think it introduces a one-turn delay? However, consider the case of a simple duplicater transform: transform(chunk, enqueue, done, close, error) {
enqueue(chunk);
enqueue(chunk);
done();
} could become transform(chunk, enqueue, close) {
enqueue(chunk);
enqueue(chunk);
} which is a lot nicer. (But this time you definitely get a one-turn delay before we can call transform(chunk, enqueue, done, close, error) {
getAsyncData(chunk).then(d => { enqueue(d); done(); }, error);
} becomes transform(chunk, enqueue, close) {
return getAsyncData(chunk).then(enqueue);
} One thing that has me confused is that the current transform implementation doesn't pass I am actually somewhat convinced now that transform is more like writable than readable, contradicting my position from the OP. So it seems pretty clear that we want to be able to return promises from However, I'm not as sure about whether we want to use promises for readable-stream This is still in my sprint for this week; hopefully I can figure out the modification to |
See discussion in #185 for background. This allows more convenient integration with promise-returning underlying source functions, removing the need for `.catch(error)` as seen in the modified example. It also rationalizes the slightly-strange way in which pull() is mutexed based on whether enqueue() has been called: instead, it is now mutexed so as to not be called again until the previous iteration's promise has fulfilled. This gives more direct control to the underlying source, and allows them to deal more easily with cases where there are just no chunks to enqueue. Although superficially it seems this may reduce performance for cases where underlying sources can enqueue many chunks synchronously, this is not actually the case, as can be seen from the modified test illustrating such a scenario. If an underlying source can enqueue multiple chunks synchronously, then it should just do so! It shouldn't wait to be pull()ed, as the previous test was doing.
#272 fixes this for readable streams. I will leave this open to track updating transform streams for a future sprint when I focus on those, but remove the "Week of 2015-01-19" milestone since the portion I wanted to accomplish last week is now finished. |
See discussion in #185 for background. This allows more convenient integration with promise-returning underlying source functions, removing the need for `.catch(error)` as seen in the modified example. It also rationalizes the slightly-strange way in which pull() is mutexed based on whether enqueue() has been called: instead, it is now mutexed so as to not be called again until the previous iteration's promise has fulfilled. This gives more direct control to the underlying source, and allows them to deal more easily with cases where there are just no chunks to enqueue. Although superficially it seems this may reduce performance for cases where underlying sources can enqueue many chunks synchronously, this is not actually the case, as can be seen from the modified test illustrating such a scenario. If an underlying source can enqueue multiple chunks synchronously, then it should just do so! It shouldn't wait to be pull()ed, as the previous test was doing.
See discussion in #185 for background. This allows more convenient integration with promise-returning underlying source functions, removing the need for `.catch(error)` as seen in the modified example. It also rationalizes the slightly-strange way in which pull() is mutexed based on whether enqueue() has been called: instead, it is now mutexed so as to not be called again until the previous iteration's promise has fulfilled. This gives more direct control to the underlying source, and allows them to deal more easily with cases where there are just no chunks to enqueue. Although superficially it seems this may reduce performance for cases where underlying sources can enqueue many chunks synchronously, this is not actually the case, as can be seen from the modified test illustrating such a scenario. If an underlying source can enqueue multiple chunks synchronously, then it should just do so! It shouldn't wait to be pull()ed, as the previous test was doing.
See discussion in #185 for background. This allows more convenient integration with promise-returning underlying source functions, removing the need for `.catch(error)` as seen in the modified example. It also rationalizes the slightly-strange way in which pull() is mutexed based on whether enqueue() has been called: instead, it is now mutexed so as to not be called again until the previous iteration's promise has fulfilled. This gives more direct control to the underlying source, and allows them to deal more easily with cases where there are just no chunks to enqueue. Although superficially it seems this may reduce performance for cases where underlying sources can enqueue many chunks synchronously, this is not actually the case, as can be seen from the modified test illustrating such a scenario. If an underlying source can enqueue multiple chunks synchronously, then it should just do so! It shouldn't wait to be pull()ed, as the previous test was doing.
Align with the WritableStream API. This resolves issues whatwg#518, whatwg#498, whatwg#331, and whatwg#185.
Align with the WritableStream API. This resolves issues whatwg#518, whatwg#498, whatwg#331, and whatwg#185.
Align with the WritableStream API. This resolves issues whatwg#518, whatwg#498, whatwg#331, and whatwg#185.
Branched from https://github.com/whatwg/streams/pull/180/files#r16783645
tyoshino
domenic
The text was updated successfully, but these errors were encountered: