Hacker News

És possible una API de fluxos millor per a JavaScript

Comentaris

16 min read Via blog.cloudflare.com

Mewayz Team

Editorial Team

Hacker News

L'API Streams de JavaScript té un problema, i els desenvolupadors finalment en parlen

Si alguna vegada heu provat d'utilitzar l'API Streams a JavaScript per a qualsevol cosa més enllà d'un exemple de llibre de text, heu sentit la fricció. El que hauria de ser una abstracció elegant i composable per a la gestió de dades seqüencials (llegir fitxers, processar respostes HTTP, transformar conjunts de dades en temps real) sovint es converteix en un boilerplate detallat, una semàntica de contrapressió confusa i una superfície d'API que s'assembla més a Java empresarial que a JavaScript modern. La conversa al voltant de la construcció d'un primitiu de transmissió millor ha estat bullint a les propostes TC39, les discussions marc i els projectes de codi obert durant anys. El 2026, està arribant a un punt d'inflexió. La pregunta no és si és possible una API de fluxos millor, sinó com sembla realment "millor" i què ens ha frenat.

On l'API Current Streams es queda curta

L'estàndard WHATWG Streams, que impulsa ReadableStream, WritableStream i TransformStream en navegadors i temps d'execució com Node.js i Deno, va ser un autèntic assoliment d'enginyeria. Va aportar contrapressió, cancel·lació i iteració asíncrona a la gestió de dades natives del web. Però a la pràctica, l'API demana massa al desenvolupador per a operacions comunes. La creació d'un flux de transformació senzill requereix crear una instancia d'un TransformStream amb un mètode transform, gestionar controladors i gestionar acuradament la semàntica d'encaix, tot per al que equival a un map() en trossos.

Compareu això amb com treballen els desenvolupadors amb matrius. Array.prototype.map(), filter() i reduce() són componibles, llegibles i requereixen gairebé zero cerimònia. L'API Streams no ofereix res d'aquesta composició ergonòmica fora de la caixa. La canalització de fluxos junts mitjançant .pipeThrough() funciona, però la construcció de les etapes de transformació és on els desenvolupadors perden hores i paciència. La gestió d'errors a través de les cadenes canalitzades és un altre problema: els errors no es propaguen de manera intuïtiva, i la depuració d'una canalització trencada sovint significa inserir transformacions de registre temporals només per esbrinar on s'estan deixant caure o es corrompen les dades.

També hi ha l'elefant Node.js a la sala. Node té la seva pròpia implementació de flux heretada (stream.Readable, stream.Writable), que és anterior a l'estàndard WHATWG gairebé una dècada. Els dos sistemes només són interoperables mitjançant utilitats d'adaptadors, i molts paquets npm encara utilitzen l'API més antiga. Els desenvolupadors que treballen en diferents entorns (renderització del costat del servidor, funcions de punta, processament basat en navegador) es veuen obligats a fer malabars amb dues abstraccions incompatibles per al mateix concepte.

Com podria semblar una API Better Streams

Algunes propostes i experiments de la comunitat apunten cap a un futur més adequat per als desenvolupadors. Les idees bàsiques segueixen convergint en uns quants principis: composició funcional, alineació de l'iterador asíncron i reducció del boilerplate. Imagineu-vos que podeu escriure canalitzacions de dades en streaming tan naturalment com escriviu transformacions de matriu: encadenant .map(), .filter() i .take() directament en un flux llegible sense necessitat de construir objectes TransformStream intermedis.

Això no és hipotètic. La proposta d'Ajudants d'Iterator (ara a l'etapa 4 del TC39) ja inclou .map(), .filter(), .take(), .drop() i .flatMap() als iterators sincronitzats. Estendre aquest patró als iteradors asíncrons —i, per extensió, als fluxos llegibles que exposen [Symbol.asyncIterator] — és un pas següent natural. Alguns temps d'execució i biblioteques ja han començat a experimentar amb aquest enfocament, permetent als desenvolupadors escriure codi com:

L'abstracció de transmissió més potent és la que desapareix. Quan els desenvolupadors poden expressar les transformacions de dades com una cadena de funcions senzilles, sense preocupar-se pels controladors, les estratègies de cua o la contrapressió manual, creen més ràpidament, envien menys errors i gaudeixen de treballar amb dades en temps real.

L'objectiu no és substituir completament l'API Streams de baix nivell. Sempre hi haurà casos d'ús: protocols personalitzats, control de memòria fi, implementacions de còdecs binaris, on l'accés directe al controlador és essencial. Però per al 90% dels casos d'ús que impliquen llegir, transformar i escriure dades seqüencials, la capa d'abstracció hauria de coincidir amb la simplicitat de la tasca.

Lliçons d'altres ecosistemes

JavaScript no és el primer llenguatge que lluita amb l'ergonomia de la reproducció en temps real. Els trets Iterador i Stream de Rust ofereixen una abstracció componible i de cost zero que permet als desenvolupadors encadenar operacions sense assignar col·leccions intermèdies. El mòdul Stream d'Elixir proporciona una enumeració mandrosa amb una sintaxi neta i fàcil de canalitzar. Fins i tot Java, sovint criticat per la seva verbositat, va introduir java.util.stream.Stream a Java 8 amb una API fluida que els desenvolupadors de JavaScript reconeixien i envejarien.

El que comparteixen aquests ecosistemes és el compromís de fer trivial el cas comú. La lectura d'un fitxer, el filtratge de línies i l'escriptura de resultats requereixen entre 3 i 5 línies de codi compostable. A l'API actual de Streams de JavaScript, la mateixa operació es pot expandir fàcilment a 20-30 línies quan es té en compte la construcció del flux, la gestió d'errors i el desmuntatge adequat. El buit no es tracta de la capacitat, sinó de l'ergonomia.

L'enfocament de Python també és instructiu. Les funcions del generador amb rendiment proporcionen una manera natural de produir i consumir dades seqüencials de manera mandrosa. JavaScript també té funcions de generador, però per connectar-les a l'API Streams requereix embolicar-les en constructors ReadableStream amb controladors basats en pull. Una integració més estreta entre generadors i fluxos, on una funció de generador podria convertir-se directament en un flux llegible, eliminaria tota una categoria de boilerplate.

L'impacte del món real en el desenvolupament d'aplicacions

Això no és una preocupació acadèmica. La transmissió de dades és el cor de les aplicacions web modernes. Esdeveniments enviats pel servidor, respostes HTTP fragmentades, taulers d'anàlisi en temps real, processament de càrrega de fitxers, flux de sortida de model d'IA: aquestes són funcions quotidianes, no casos extrems. Quan la primitiva de reproducció en temps real és difícil d'utilitzar, els desenvolupadors l'evitan completament (emmagatzemant tot a la memòria, que no s'escala) o construeixen canalitzacions fràgils i difícils de mantenir que es converteixen en una font d'incidents de producció.

Penseu què passa a escala. Una plataforma com Mewayz, que processa dades a través de 207 mòduls empresarials integrats, des de pipelines CRM i facturació fins a càlculs de nòmines i seguiment de la flota, gestiona internament enormes volums de dades seqüencials. Les operacions d'exportació, la generació d'informes, el processament d'esdeveniments de webhook i les actualitzacions del tauler de control en temps real es beneficien d'una transmissió eficient. Quan les primitives del llenguatge subjacent dificulten la transmissió, el cost es multiplica a cada mòdul i a cada flux de dades. Els enginyers de la plataforma acaben construint abstraccions de transmissió internes a sobre de les abstraccions del llenguatge, afegint complexitat que no hauria de ser necessària.

💡 DID YOU KNOW?

Mewayz replaces 8+ business tools in one platform

CRM · Invoicing · HR · Projects · Booking · eCommerce · POS · Analytics. Free forever plan available.

Start Free →
  • Processament de fitxers: penjar i analitzar fitxers CSV amb més de 100.000 files requereix la reproducció en temps real per evitar l'esgotament de la memòria, però l'API actual fa que fins i tot la transformació bàsica fila per fila sigui detallada
  • Taulers de control en temps real: la transmissió de dades d'anàlisi del servidor al client mitjançant SSE o WebSocket es beneficia de transformacions composables (agregació, filtratge, limitació) que és difícil d'expressar avui en dia
  • Transmissió de respostes d'IA: a mesura que les funcions basades en LLM esdevenen estàndard a les eines empresarials, la transmissió de respostes testimoni per testimoni a la interfície d'usuari és una expectativa bàsica i un cas d'ús perfecte per a transformacions de flux encadenables
  • Operacions per lots: el processament de nòmines de milers d'empleats, la generació de factures massives o la sincronització de registres de CRM amb sistemes externs impliquen la transmissió de dades mitjançant fases de validació, transformació i sortida
  • Conductes de webhook: la ingestió, validació, encaminament i processament d'esdeveniments de webhook entrants procedents d'integracions de tercers és inherentment una càrrega de treball en temps real

Què es proposa realment

L'ecosistema JavaScript s'està movent en diversos fronts. La proposta d'Ajudants d'iteradors de TC39 ja ha arribat, aportant la composició funcional als iteradors sincrònics. L'extensió natural —Async Iterator Helpers — portaria els mateixos mètodes .map(), .filter(), .reduce(), .take() i .flatMap() per implementar iteradors asíncrons que ja es poden llegir. [Symbol.asyncIterator]. Només això milloraria dràsticament l'experiència dels desenvolupadors dels patrons de reproducció en temps real més habituals.

Més enllà del TC39, les innovacions a nivell d'execució també estan superant el límit. Deno ha experimentat amb utilitats de flux més ergonòmics. La caixa d'eines de Web Streams i biblioteques comunitàries similars ofereixen funcions d'ajuda que engloben les parts detallades de l'API. I hi ha un impuls creixent darrere de la idea d'una biblioteca estàndard nativa del flux: un conjunt d'utilitats integrades i optimitzades per a operacions de transmissió habituals com la divisió de línies, l'anàlisi JSON, el processament CSV i la compressió que els desenvolupadors treuen actualment de npm.

També hi ha un argument convincent per a una millor semàntica dels errors. A l'API actual, un error en una cadena canalitzada pot deixar els fluxos en estats ambigus, parcialment consumits, amb bloquejos penjants als lectors. Una API revisada podria adoptar una propagació d'errors estructurada semblant al tipus Result de Rust o adoptar una convenció on els errors flueixin a través de la canalització com a valors, permetent que les etapes posteriors se'n gestionen o es recuperin sense trencar tota la cadena. Això seria transformador per a la fiabilitat de la producció.

Per què això és més important que mai el 2026

Tres tendències convergents fan que l'ergonomia de l'API de transmissió sigui més urgent ara que en qualsevol moment de la història de JavaScript. En primer lloc, la informàtica de punta (Cloudflare Workers, Vercel Edge Functions, Deno Deploy) funciona sota estrictes restriccions de memòria i CPU on la memòria intermèdia de respostes o conjunts de dades sencers simplement no és viable. La reproducció en temps real és l'única opció, i els desenvolupadors que es desenvolupen en aquests entorns necessiten una API que no els lluiti.

En segon lloc, la integració de l'IA ha fet que la transmissió sigui una funció orientada a l'usuari. Quan un assistent d'IA genera una resposta, els usuaris esperen veure com apareixen fitxes en temps real, no esperar que s'amortitzi tota la resposta. Totes les plataformes SaaS, des de sistemes operatius empresarials com Mewayz fins a eines d'IA autònomes, ara necessiten un consum de flux robust al costat del client. L'API actual funciona per a això, però l'experiència dels desenvolupadors d'anàlisi, transformació i representació de la sortida d'IA en temps real podria ser molt millor amb operadors de reproducció de reproduccions.

En tercer lloc, el moviment de JavaScript de pila completa significa que els desenvolupadors estan gestionant fluxos a banda i banda del límit de la xarxa. Un únic enginyer pot escriure un flux del costat del servidor que processi els resultats de la consulta de la base de dades, els canalitza a través d'una transformació, els envia com a resposta HTTP fragmentada i després consumeix el mateix flux al client per representar una interfície d'usuari progressiva. Quan l'API de transmissió és incòmode, aquesta fricció es nota a totes les capes de la pila.

Avançar: què poden fer els desenvolupadors avui

Mentre el llenguatge evoluciona, els desenvolupadors no es queden esperant. Diverses estratègies pràctiques poden millorar l'experiència de streaming en projectes actuals. L'ús de generadors asíncrons com a patró de creació principal —i embolicar-los a ReadableStream.from() on el temps d'execució ho admet— proporciona una sintaxi molt més neta que la gestió manual del controlador. Biblioteques com it-pipe i iterables en temps real ofereixen ajudants componibles que ofereixen un encadenament funcional als iteradors asíncrons actuals.

Per als equips que creen aplicacions intensives en dades, invertir en una fina capa d'utilitat de reproducció interna té beneficis. Un conjunt de funcions streamMap(), streamFilter() i streamBatch() ben dissenyades, cadascuna pren un iterable asíncron i retorna un iterable asíncron, proporciona la composició que no té l'API estàndard, sense el pes d'un marc de reproducció complet. Aquest és el patró que escala des dels prototips d'inici fins a les plataformes que gestionen milions d'operacions.

  1. Adopta generadors asíncrons com a patró predeterminat per produir dades en temps real: són més nets, més comprovables i més componables que la construcció manual ReadableStream
  2. Utilitzeu ReadableStream.from() per connectar iterables asíncrons al món dels fluxos web quan necessiteu una interacció amb API que esperen instàncies de ReadableStream
  3. Crear o adoptar funcions d'utilitat prims per a operacions habituals (mapa, filtre, lots, acceleració) sobre iterables asíncrons en lloc de construir objectes TransformStream
  4. Advocat en TC39 i debats en temps d'execució: la proposta d'ajudants de l'iterador asíncron necessita veus dels desenvolupadors que impulsin la priorització
  5. Escriu proves amb iterables asíncrons, no transmet directament; això fa que la teva lògica de transmissió sigui portàtil i més fàcil de validar

L'API JavaScript Streams era una base necessària. Però s'han de construir les bases i la següent capa d'abstracció, una que fa que la transmissió sigui tan natural com treballar amb matrius, s'ha acabat. Les peces estan al seu lloc: iteradors asíncrons, funcions del generador i el patró d'ajudants de l'iterador. El que es necessita ara és la voluntat col·lectiva de reunir-los en un estàndard que coincideixi amb com els desenvolupadors pensen realment sobre les dades seqüencials. El resultat no serà només una API millor, sinó que desbloquejarà la transmissió com a patró predeterminat en lloc d'un últim recurs, fent que les aplicacions siguin més ràpides, més eficients en memòria i més agradables de crear.

Preguntes més freqüents

Què passa amb l'API JavaScript Streams actual?

L'API actual de Streams pateix un excés d'excés, una semàntica de contrapressió confusa i una superfície de l'API massa complexa que descoratja l'adopció. Les tasques senzilles com llegir un fitxer o processar una resposta HTTP requereixen molt més codi del necessari. Sovint, els desenvolupadors recorren a biblioteques de tercers o patrons més antics, com ara devolucions de trucada i emissors d'esdeveniments, obviant completament l'estàndard perquè l'ergonomia sembla més propera a Java empresarial que al JavaScript modern.

Com podria millorar el desenvolupament web una API de Streams millor?

Una API de Streams redissenyada amb una sintaxi més neta, suport d'iteració asíncrona integrada i mètodes de composició intuïtius simplificaria dràsticament el processament de dades en temps real. Els desenvolupadors podrien encadenar transformacions de manera natural, gestionar la contrapressió de manera transparent i escriure canalitzacions de transmissió en una fracció del codi. Això faria que la renderització progressiva, les fonts de dades en directe i el processament de fitxers grans fossin accessibles per a tots els desenvolupadors de JavaScript, no només per a aquells disposats a lluitar amb primitives de baix nivell.

Les plataformes empresarials modernes poden gestionar la transmissió de dades en temps real de manera eficaç?

Sí: plataformes com Mewayz, un sistema operatiu empresarial de 207 mòduls a partir de 19 dòlars al mes, ja aprofiten canalitzacions de dades eficients darrere de l'escenari per a l'anàlisi, els fluxos de treball d'automatització i els informes en directe. A mesura que els estàndards de transmissió milloren a JavaScript, les eines construïdes a la pila web oferiran experiències en temps real encara més ràpides, des d'actualitzacions instantànies del tauler de control fins al processament de fitxers sense problemes en els mòduls empresarials integrats.

Quines alternatives existeixen mentre l'API Streams evoluciona?

Actualment, els desenvolupadors confien en biblioteques com els fluxos de Node.js, RxJS per a la programació reactiva o generadors asíncrons combinats amb bucles d'espera per gestionar les dades seqüencials de manera més ergonòmica. Els polyfills compatibles amb la web i els ajudants d'etapa de proposta també superen els buits de l'API estàndard. La clau és triar abstraccions que s'alinein amb el vostre cas d'ús, tant si això significa patrons observables per a aplicacions amb esdeveniments pesats com una simple iteració asíncrona per a tasques senzilles de transformació de dades.