Top
Best
New

Posted by nnx 12 hours ago

A better streams API is possible for JavaScript(blog.cloudflare.com)
361 points | 118 commentspage 3
adamnemecek 7 hours ago|
It might be a good idea to look into the research on streams as coalgebras, there is quite a bit, for example here https://cs.ru.nl/~jrot/CTC20/.

Coalgebras might seem too academic but so were monads at some point and now they are everywhere.

ralusek 10 hours ago||
I tinkered with an alternative to stream interfaces:

https://github.com/ralusek/streamie

allows you to do things like

    infiniteRecords
    .map(item => doSomeAsyncThing(item), { concurrency: 5 });
And then because I found that I often want to switch between batching items vs dealing with single items:

    infiniteRecords
    .map(item => doSomeAsyncSingularThing(item), { concurrency: 5 })
    .map(groupOf10 => doSomeBatchThing(groupsOf10), { batchSize: 10 })
    // Can flatten back to single items
    .map(item => backToSingleItem(item), { flatten: true });
murmansk 10 hours ago||
For gods sake, finally, somebody have said this!
paulddraper 10 hours ago||
Just use AsyncIterator<UIntArray>.

The objection is

> The Web streams spec requires promise creation at numerous points — often in hot paths and often invisible to users. Each read() call doesn't just return a promise; internally, the implementation creates additional promises for queue management, pull() coordination, and backpressure signaling.

But that's 95% manageable by altering buffer sizes.

And as for that last 5%....what are you doing with JS to begin with?

ai-christianson 11 hours ago||
[flagged]
slowcache 10 hours ago||
> high-performance data processing tools in JS

I may be naive in asking this, but what leads someone to building high perf data tools in JS? JS doesn't seem to me like it would be the tool of choice for such things

n_e 10 hours ago|||
I have a SaaS project where the backend is in JS. I also have some data processing to do with large file (several TB). Doing it is in JS is more convenient as I can reuse code from the backend, and it is also the language I know best.

Performance-wise, I get about half the throughput I had with the same processsing done it rust, which doesn't change anything for my use-case.

However that's not really relevant to the context of the post as I'm using node.js streams which are both saner and fast. I'm guessing that the post is relevant to people using server-side runtimes that only implement web streams.

afavour 9 hours ago||||
Browsers are now able to stream files from disk so you can create a high performance tool that'll read locally, do [x] with it and present the results, all without any network overhead.
moron4hire 10 hours ago||||
You don't always have a choice on where you deliver your software. It'd be nice to have good tools wherever you are forced to work.
thadt 10 hours ago|||
Browsers
speed_spread 10 hours ago||
Since when are browsers themselves built in JavaScript? Mainstream, fast ones?
thadt 9 hours ago|||
Clarification - in the past when I've written high performance data tools in JS, it was almost entirely to support the use case of needing it to run in a browser. Otherwise, there are indeed more suitable environments available.

To your question, I was about to point out Firefox[1], but realized you clarified 'mainstream'[2]...

[1] https://briangrinstead.com/blog/firefox-webcomponents

[2] https://gs.statcounter.com/browser-market-share

jitl 9 hours ago||
but instead of trying to solve that, this api is just like “too hard no one uses it let’s forget about it”.

right now when i need to wrangle bytes, i switch languages to Golang. it’s easy gc language, and all its IO is built around BYOB api:

interface Reader { read(b: Uint8Array): [number, Error?] }

you pass in your own Uint8Array allocation (in go terms, []byte), the reader fills at most the entire thing, and returns (bytes filled, error). it’s a fully pull stream API with one method at its core. now, the api gets to be that simple because it’s always sync, and blocks until the reader can fill data into the buffer or returns an error indicating no data available right now.

go has a TeeReader with no buffering - it too just blocks until it can write to the forked stream.

https://pkg.go.dev/io#TeeReader

we can’t do the same api in JS, because go gets to insert `await` wherever it wants with its coroutine/goroutine runtime. but we can dream of such simplicity combined with zero allocation performance.

animanoir 10 hours ago||
[dead]
Feathercrown 11 hours ago||
[flagged]
user3939382 11 hours ago||
“ The Streams Standard was developed between 2014 and 2016 with an ambitious goal to provide "APIs for creating, composing, and consuming streams of data that map efficiently to low-level I/O primitives." Before Web streams, the web platform had no standard way to work with streaming data.”

This is what UDP is for. Everything actually has to be async all the way down and since it’s not, we’ll just completely reimplement the OS and network on top of itself and hey maybe when we’re done with that we can do it a third time to have the cloud of clouds.

The entire stack we’re using right down to the hardware is not fit for purpose and we’re burning our talent and money building these ever more brittle towering abstractions.

afavour 11 hours ago||
UDP is a protocol, not an API
mlhpdx 9 hours ago||
True. But it’s also true that trying to shoehorn every use case into TCP streams is counter productive.

A stream API can layer over UDP as well (reading in order of arrival with packet level framing), but such a stream would a bit weird and incompatible with many stream consumers (e.g. [de]compression). A UDP API is simpler and more naturally event (packet) oriented. The concepts don’t mix well.

Still, it would be nice if they browser supported a UDP API instead of the weird and heavy DTLS and QUIC immitations.

kaoD 5 hours ago|||
TCP or UDP are orthogonal to this, so the original comment feels like a non sequitur. These streams are not network streams and could be a file, chunks of procedural audio, or whatever.
mlhpdx 42 minutes ago||
I agree, the stream concept should be (and is) very general and ideally cover all these cases - any “bytes producing” source.

I was trying to be open minded about that and conceive a stream API over a UDP socket. It’d work IMHO, but be a little odd compared to an event-like API.

drysart 6 hours ago|||
The browser does have a UDP data stream available for applications to send arbitrary bytes over UDP; it's part of WebRTC.
mlhpdx 49 minutes ago||
While Web RTC is built on UDP, it does not allow sending arbitrary UDP. It's DTLS, perhaps encapsulating SCTP, and DCEP.
delaminator 10 hours ago||
We're too busy building products while waiting for the perfect system to arrive.
user3939382 10 hours ago||
I’m building everything from first principles, I’m not climbing the exponential curve with some billionaire that has to finance it.
delaminator 10 hours ago||
I really doubt you are. you're not visiting the transistor shop every time you want to build a react component
user3939382 9 hours ago||
Good thing your confidence is a soft requirement :)
shevy-java 11 hours ago|
We deserve a better language than JavaScript.

Sadly it will never happen. WebAssembly failed to keep some of its promises here.

gejose 10 hours ago||
There's always a comment like this in most discussions about javascript.
krashidov 9 hours ago|||
> WebAssembly failed to keep some of its promises here

classic case of not using an await before your promise

teaearlgraycold 7 hours ago|||
As wonky as JS is I really like it. Typescript has done such a good job at making it fun to use.
tprgoreturnon 3 hours ago||
[dead]
postalrat 10 hours ago||
Where can I find these not kept promises?
nindalf 10 hours ago||
They haven't yet made languages other than JavaScript first-class languages for the web - https://hacks.mozilla.org/2026/02/making-webassembly-a-first.... I wouldn't call this a broken promise, but it was something people were hoping would take less than a decade.