Node: Implementar window.fetch en el núcleo

Creado en 16 mar. 2018  ·  158Comentarios  ·  Fuente: nodejs/node

https://github.com/bitinn/node-fetch

Tendría sentido si window.fetch se implementara en el núcleo. parece ser una API lo suficientemente estable que sería una buena candidata para su inclusión. No estoy seguro de cuál es el proceso desde aquí, pero pensé en plantear un problema :)

feature request http http2

Comentario más útil

Esto definitivamente sería útil en API multiplataforma simples y creo que es para lo que mucha gente ya usa node-fetch. También sería bueno si la negociación HTTP/1 v HTTP/2 también se puede manejar automáticamente como en los navegadores.

Todos 158 comentarios

esto ha surgido de vez en cuando, pero todavía no ha tenido mucha tracción. A ver que opina la gente :-)

bradley y yo estábamos discutiendo esto de forma indirecta sobre el tema de import ing desde urls. si se introdujera esa función (y creo que, en general, la queremos), necesitaríamos implementar esto: https://html.spec.whatwg.org/multipage/webappapis.html#fetch -a-single-module-script que utiliza la especificación fetch. como otra nota, si esto se agregó en el núcleo, me gustaría extraer una implementación de c ++ existente de uno de los navegadores. sin embargo, como mínimo, el nodo definitivamente agregará objetos Request y Response , es posible que no agregue una función llamada fetch

-1 este tipo de funcionalidad de alto nivel es mejor dejarla en manos del usuario

Esto definitivamente sería útil en API multiplataforma simples y creo que es para lo que mucha gente ya usa node-fetch. También sería bueno si la negociación HTTP/1 v HTTP/2 también se puede manejar automáticamente como en los navegadores.

¡Me encantaría esto! ❤️

Isomorphic JS es una de las principales razones por las que las personas que comienzan con JS en el front-end, finalmente eligen Node.js en el back-end.

Puede ejecutar exactamente la misma función en el navegador y el servidor, y el único lugar de disputa que sigo encontrando es window.fetch.

Parte del código que se ejecuta en el servidor y el cliente necesita realizar solicitudes HTTP a otro servidor (piense en microservicios con representación del lado del servidor y representación del lado del cliente).

Un caso para llevarlo al núcleo es que hacer solicitudes HTTP (cliente) está estrechamente relacionado con responder a solicitudes HTTP (servidor).

Y ahora tenemos un análisis de URL isomorfo, ¡así que ahora todo lo que necesitamos es buscar! ¡Hagamos que la búsqueda suceda!

Fetch es de 'bajo nivel' según su autor y principal partidario, por lo tanto, falta un montón de características como soporte para tipos de contenido, JSON no es predeterminado, no hay codificación de cadena de consulta. Las aplicaciones que necesitan un cliente HTTP de calidad de alto nivel disponible en todos los entornos de JavaScript pueden continuar usando superagent.

@mikemaccana la búsqueda de la que estamos hablando es https://fetch.spec.whatwg.org/ y no creo que sea apropiado conectar otras bibliotecas http

@devsnek Sí, lo sé, ese es al que me refería específicamente. No disfruto particularmente del superagente aparte de que es:

  • un cliente HTTP con todas las funciones
  • disponible en el nodo y el navegador
  • más popular que buscar
  • tiene JSON por defecto
  • codifica cadenas de consulta
  • usa tipos de contenido para determinar el cuerpo de la respuesta
  • usa verbos HTTP como nombres de métodos, por lo que puede felizmente .get() y .post() cosas en lugar de 'obtener con el método POST', que es un modelo mental algo extraño

Si fetch admitiera esto, sugeriría que se incluyera en node. Para repetir: le pregunté al autor y principal proponente de fetch, Jake Archibald, por qué no es compatible con estas cosas y se afirma que fetch está diseñado para ser una API de bajo nivel y cosas como valores predeterminados sensibles pueden/deben agregarse por un nivel superior API. Como resultado, no veo ninguna razón para usar fetch en el nodo o en el navegador.

@mikemaccana

En realidad, estas son propiedades deseables para el argumento de incluir fetch en el núcleo de Node.js, si queremos mantener el núcleo pequeño y de bajo nivel. Creo que eventualmente tendremos que proporcionar una API prometida para http/http2 de todos modos, y obtener como una especificación existente para un conjunto similar de funcionalidad de bajo nivel como nuestro http es algo que vale la pena considerar. En mi experiencia, las piezas que faltan en la búsqueda se sienten bastante similares a las piezas que faltan en el http de Node.js, la principal diferencia es que tiene una API especificada con la que contar.

También dudo un poco de la parte "más popular que buscar", no creo que haya tanta gente que use super-agente en el navegador como en Node, dado que buscar simplemente existe en el navegador (situaciones de módulo que necesitan polyfills)?

Aunque, antes de comenzar a implementar fetch, creo que necesitaremos introducir la API de flujo en el navegador . ¿Se está introduciendo otra transmisión en Node.js sobre la mesa?

La única vez que me vi obligado a recurrir a XHR en el navegador fue cuando necesitaba progresar, aunque creo que con ReadableStreams del navegador es posible hacer lo mismo con una API que es un poco incómoda ( res.body.read().byteLength ) - si implementaría el progreso en Node.js, creo que necesitaría usar chunk.byteLength del fragmento que se emite en el evento data , que es donde comienza la diferencia entre las dos transmisiones importar.

Además, la especificación de recuperación no parece incluir el tiempo de espera o los agentes (¿todavía?) en este momento, es posible que falten más funcionalidades en comparación con nuestra API http existente. Como referencia, node-fetch parece implementar estas opciones no estándar. Una vez más, no estoy seguro de si nuestra implementación debería implementar funcionalidades no estándar, incluso si proporcionan las piezas que faltan en comparación con la API anterior.

también cc @TimothyGu , ¿te podría interesar?

@thecodingdude

totalmente en desacuerdo; Node usa v8 y, por extensión, debe implementar tantas características como sea posible de v8 que tengan sentido. fetch es uno de esos en los que los desarrolladores no necesitarían npm install request o node-fetch, que son bibliotecas muy populares, por lo que esta funcionalidad garantiza estar en el núcleo.

Sin embargo, técnicamente, buscar no es una característica de v8, es una API especificada por WHATWG, mientras que v8 implementa ECMA-262, una especificación de ECMA TC39; v8 expone.

Por cierto: ¿no creo que estemos hablando de llevar paquetes npm al núcleo? Más bien, estamos hablando de implementar la especificación por nuestra cuenta e incorporar el WPT para probar el cumplimiento, posiblemente con un montón de código escrito en C++, muy parecido a lo que hicimos para la URL de WHATWG.

@thecodingdude, la continua popularidad de las bibliotecas que no son de búsqueda no es una opinión personal, es un hecho: superagent tuvo 1,6 millones de descargas esta semana . Tampoco es la falta de valores predeterminados razonables de alto nivel en fetch: nuevamente (otra vez) eso es reconocido por el autor de fetch. Por favor, no reformule hechos técnicos objetivos verificables como opiniones subjetivas irrelevantes porque no le gustan.

por favor, no conecte otras bibliotecas aquí, son irrelevantes para nuestra discusión.

los desarrolladores no necesitarían npm install request o node-fetch

😂👍

Personalmente soy -1 por dos razones:

  1. Tener dos API diferentes ( fetch() y http.request() ) para hacer lo mismo no es coherente.

  2. fetch() no es lo suficientemente flexible para admitir cosas como proxy, certificados TLS personalizados, etc. El navegador lo maneja de manera transparente, pero eso no funcionará en node.js.

actualmente, 84 personas están de acuerdo

Yo no le daría demasiada importancia a eso. Las encuestas de GH se manipulan fácilmente a través de brigadas de Twitter y otras cosas. Los tomaría más en serio si me costara un dólar emitir un voto a favor.

thecodingdude He comentado con una lista de viñetas de razones técnicas por las que fetch no es adecuado como un cliente HTTP de propósito general. Soy consciente de que "no te importa qué tan bueno o malo sea". Creo que esto está mal: el nodo debe elegir y adoptar API de calidad. El hecho de que personalmente no esté interesado en la calidad de fetch no significa que sea irrelevante para la discusión. Los proveedores de navegadores estaban comparando fetch con window.xhr, node no.

@mikemaccana ¿Por qué fetch necesita tener características de alto nivel como "verbos HTTP como nombres de métodos" para que se incluya en el núcleo? Puede escribir trivialmente sus propios métodos que hacen esto, además de las otras características de alto nivel que ha mencionado.

Lo bueno de tener API estándar compartidas tanto en el navegador como en Node es que al escribir la API de alto nivel para apuntar a la de bajo nivel (en este caso fetch ) puede obtener un comportamiento consistente mucho más fácilmente que tener que hacer que su API funcione en torno a las diferencias entre las diferentes API en el nodo y el navegador.

@thecodingdude ¿ alguna razón por la que esto se cerró? la discusión todavía parece estar en movimiento

@devsnek , sí, no estoy satisfecho con la forma en que se desarrolló esta discusión y el problema, y ​​me doy cuenta de que los problemas de github simplemente no son el foro apropiado para discutir si las funciones deberían aterrizar en el núcleo. Prefiero mucho más los node-eps ya que ese fue un documento adecuado que describe la propuesta. Mi intención era recopilar los pensamientos del equipo central y de cualquier otra persona involucrada en la fusión de funciones en el núcleo (planificación, codificación, pruebas, etc.). En cambio, la discusión aquí hasta ahora es básicamente sin sentido. Debería ser sobre la viabilidad, lo que se requeriría y cuándo podría fusionarse dicha característica.

Eche un vistazo a este problema e intente seguir la avalancha de conversaciones sobre websockets en el núcleo. Hay demasiado ruido y no hay un enfoque sencillo para proponer nuevas funciones. Creo que el sistema rfc de PHP es un buen ejemplo de cómo agregar nuevas funciones. Claro, conciso, responsable.

Estoy dispuesto a discutir un _rfc_ y sus méritos en una edición separada, pero está claro que esto no va a ninguna parte, con poca o ninguna interacción de TSC o cualquier otra persona que importe, por lo que no tiene sentido dejarlo solo para enviar spam a las bandejas de entrada de las personas.

Me abstendré de hacer tales problemas en el futuro, mi mal.
cc @jasnell

@Jamesernator ¿Por qué fetch necesita tener funciones de alto nivel como "verbos HTTP como nombres de métodos" para que se incluya en el núcleo? Puede escribir trivialmente sus propios métodos que hacen esto, además de las otras funciones de alto nivel que ha mencionado

Por supuesto. Yo, y todos los demás que necesitan usar cadenas de consulta , podemos escribir un método para codificar cadenas de consulta. Mejor aún: incluyamos un cliente HTTP de buena calidad y baterías incluidas en el nodo donde no todos necesiten arreglarlo.

@thecodingdude parece que eliminó su comentario, pero para responder de todos modos: HTTP2 es necesario porque se requiere hablar la versión actual de HTTP. fetch no es necesario, porque es solo uno de los muchos clientes HTTP, y no muy bueno, por las razones discutidas.

@mikemaccana Pero la razón para incluir fetch en el núcleo de Node no se trata de las baterías incluidas, es para que pueda escribir código que se dirija tanto al navegador como a Node a la vez. Es por eso que Node también es compatible con el constructor URL (e incluso ahora es global como en el navegador en el nodo 10) y los documentos incluso se refieren a los objetos url.Url antiguos como la API de URL heredada .

Esto es algo bueno, ya que significa algún módulo que usa importación dinámica, por ejemplo, no necesitan incluir ninguna biblioteca para poder cargar recursos relacionados con él, por ejemplo:

...

export default async function isWordForLanguage(language="english") {
    const wordDataUrl = new URL(`./resources/${ language }.csv`, import.meta.url)
    const words = await loadSomehow(wordDataUrl)
    return makeIsWord(words)
}

Ahora ese código no tiene un comportamiento específico de la plataforma (suponiendo un método loadSomehow que potencialmente podría ser fetch ). Los beneficios de esto deberían ser bastante obvios:

  • El uso de API que están estandarizadas e incluidas tanto en el navegador como en Node significa que obtendrá soporte en ambos contextos si hay algún problema con las implementaciones (y, por lo tanto, no hay posibilidad de bibliotecas muertas o obsoletas)
  • Bibliotecas más pequeñas para funciones de alto nivel, ya que no necesitan suavizar las diferencias de plataforma, solo usan la API universal ( URL o fetch o lo que sea) y construyen directamente sobre eso
  • Lo mismo ocurre con sus propias bibliotecas que necesitan un comportamiento de alto nivel

Creo que es un esfuerzo inútil crear otra biblioteca de http en Node si no es por la interoperabilidad. Si Node crea otro que no está en el navegador, simplemente obtiene la misma situación que tiene ahora, si desea un código interoperable con el navegador, debe construir otra biblioteca encima solo para obtener interoperabilidad con los navegadores.

Si cree que es importante que los navegadores admitan API de alto nivel listas para usar, entonces probablemente valga la pena apoyar los esfuerzos para hacer que las API de alto nivel formen parte del navegador y dejar en claro sus objetivos sobre lo que quiere ver en las API de alto nivel. Estoy seguro de que muchos desarrolladores apreciarán obtener especificaciones API de alto nivel.

Sería aún mejor si hubiera una manera de hacer que Node y los navegadores colaboraran en funciones de alto nivel. No estoy seguro de cómo podría funcionar esto, pero si pudiera hacerse, sería mucho más fácil proponer funciones de alto nivel. API que se dirigen a todos los entornos en lugar de estar aisladas en Node o en los navegadores.

Gracias @Jamesernator : es bueno saber que hay un esfuerzo para resolver esto a mayor escala. Gracias también por ser cortés y leer mis comentarios antes de responder.

Tiendo a pensar que si NodeJS se hubiera desarrollado hoy, no hay duda de que fetch se habría implementado en nombre de la alineación con las API del navegador. Sí, hay algunos casos extremos realmente interesantes, pero @TimothyGu los ha manejado muy bien en la integración de obtención de nodos.

@thecodingdude , ¿te importa si vuelvo a abrir? Potencialmente, aún podríamos tener cosas alineadas aquí: no creo que la discusión detallada haya seguido su curso por completo todavía y creo que todavía hay una discusión fructífera para tener personalmente.

@bnoordhuis node-fetch maneja las diferencias aquí al admitir la opción agent específica de NodeJS que delega funciones como proxy https://github.com/bitinn/node-fetch#options. Rompe la API universal, pero también se puede hacer de forma condicional con bastante facilidad, por lo que tiendo a pensar que parece un compromiso bastante bueno con estas cosas. También se podría decidir que tal divergencia es una mala idea, aunque ciertamente.

Sin embargo, la clave es que esta API de recuperación está restringida deliberadamente: las API HTTP y HTTP/2 siguen siendo fundamentales, esto podría proporcionar la experiencia universal fácil. No tiene nada de malo tener dos API para hacer lo mismo, cuando una se construye encima de la otra para brindar una experiencia de usuario convincente.

@guybedford siéntase libre de hacer una nueva edición discutiendo esto más a fondo si esa es la dirección más adecuada. Preferiría mucho más las discusiones técnicas sobre la implementación en sí, y no lo que hace/no hace fetch frente a las alternativas, por lo que cerré el problema en primer lugar.

Honestamente, no veo por qué esta discusión debe ocurrir en github; al menos, debe estar bloqueada para los colaboradores que van a trabajar en el código y las discusiones se centraron completamente en implementar fetch, idéntico al navegador donde sea posible, y nada más y nada menos.

@thecodingdude Todavía no estoy muy seguro de entender por qué necesita un nuevo problema aquí. Discutir los límites del problema seguramente debería ser el primer paso para cualquier característica nueva, y también se debe permitir una discusión más amplia al principio. 16 comentarios tampoco parece fuera de lugar.

Ciertamente, los tecnicismos de si debe ser JS o C++, o dónde trazar la línea sobre la agrupación y los proxies son importantes, pero las cosas tienen que seguir su propio curso.

No tiene nada de malo tener dos API para hacer lo mismo, cuando una se construye encima de la otra para brindar una experiencia de usuario convincente.

Pero no está 'encima': hacen lo mismo, solo que con diferentes interfaces.

Los argumentos a favor de fetch() se reducen a 'conveniencia', lo que no es una buena razón para incluirlo en el núcleo.

Gracias @bnoordhuis , estos son puntos importantes en cuanto a dónde está la línea en Node, y debo admitir que históricamente no estoy familiarizado con este tipo de discusiones, pero mientras Node se esfuerce por proporcionar utilidades centrales, esto parece importante para incluirme.

Pero no está 'encima': hacen lo mismo, solo que con diferentes interfaces.

Actualmente, node-fetch está construido sobre el módulo http, personalmente preferiría una implementación basada en JS aquí, trabajando exactamente desde lo que @TimothyGu ya ha construido como una de las bibliotecas más populares. El patrón de tener API de alto y bajo nivel para lo mismo está establecido.

Los argumentos a favor de fetch() se reducen a 'conveniencia', lo que no es una buena razón para incluirlo en el núcleo.

La conveniencia es un argumento muy importante, la pregunta es cuánto justificar los costos de mantenimiento. Node no solo admite módulos y enlaces nativos, sino que proporciona utilidades de servidor y API universales cuando corresponda. Como he dicho, fetch me parece una parte fundamental de la caja de herramientas universal en estos días.

Incluso presionaría para que fetch integre HTTP/2 de manera transparente en el futuro, lo que permitiría que dicha función no solo se desarrolle sobre las funciones integradas existentes, sino que también brinde una unificación que no tenemos actualmente. Sé que hay complejidades que abordar aquí, y no es un hecho, pero parece que sería una gran victoria para Node y sus usuarios.

Actualmente, node-fetch está construido sobre el módulo http

Eso es un detalle de implementación. Mirándolo desde la perspectiva de un usuario, son diferentes formas de hacer lo mismo, ninguna claramente superior.

La conveniencia es un argumento muy importante, la pregunta es cuánto justificar los costos de mantenimiento.

La interfaz pública de los módulos incorporados no se puede cambiar fácilmente, a veces no se puede cambiar en absoluto. En el mejor de los casos, sigue siendo un asunto de años. Los módulos en npm no tienen ese problema.

fetch() tiene que ser un estándar, excepto que tendríamos que extenderlo para que sea utilizable (por ejemplo, esa opción agent que mencionaste).

Parece que tendríamos que evaluar si el enfoque agent utilizado en la búsqueda de nodos sería adecuado y qué tan estable podría considerarse esta API u otra similar. Tal vez @TimothyGu pueda compartir opiniones sobre la estabilidad de estos casos para garantizar la compatibilidad con versiones anteriores de forma predeterminada.

Estoy en conflicto con este tema. Como partidario perenne del núcleo pequeño, señalo la flexibilidad para hacer cambios importantes que permite un módulo de espacio de usuario. Sin embargo, node-fetch (y la API Fetch) han sido notablemente estables: node-fetch solo tuvo un lanzamiento de última hora en los últimos años, y los cambios de última hora programados actualmente son todos logísticos (superando las versiones compatibles de Node.js y una paquete de terceros).

Por otro lado, creo que sería una experiencia mucho mejor para los usuarios si no tuvieran que instalar un paquete con el propósito básico de obtener un archivo en un script, con una interfaz con la que podrían estar familiarizados. No, http.request no cuenta como una solución, ya que habría que esforzarse más para admitir redireccionamientos, compresión y, ahora, HTTP/2 transparente.

Con respecto a la brecha de funcionalidad, @bnoordhuis mencionó:

fetch() tiene que ser un estándar, excepto que tendríamos que extenderlo para que sea utilizable (por ejemplo, esa opción agent que mencionaste).

En mi opinión, si node-fetch tiene todas sus extensiones (grep para "node-fetch extension" en README ) eliminadas, aún sería una herramienta perfectamente útil, especialmente para scripts de un solo archivo. Decirle al usuario " fetch() se ofrece solo por conveniencia, y para más funciones/personalizaciones (como la opción agent ), use node-fetch/request/etc." es una solución perfectamente viable.

Al final, me encantaría ver que fetch() y las API periféricas sean parte del núcleo.

Para que el nodo sea compatible con la recuperación, es posible que debamos realizar un par de cambios en las especificaciones para permitirle eludir cosas como CORS, pero parece factible.

Sin embargo, no creo que valga la pena considerarlo a menos que/hasta que el nodo implemente https://streams.spec.whatwg.org/ , ¡lo cual me encantaría ver! Editar: aunque, los navegadores enviaron la búsqueda antes de que aterrizaran las transmisiones, así que supongo que el nodo podría hacer lo mismo.

@mikemaccana

Fetch es de 'bajo nivel' según su autor

Es de bajo nivel para la web. Pero de alguna manera eso lo convierte en un nodo de alto nivel debido a sus requisitos de seguridad relativamente relajados. Aunque esto podría agregarse con bastante facilidad en la especificación.

y un gran partidario, por lo tanto, falta un montón de características como soporte para tipos de contenido

Fetch admite el encabezado Content-Type .

JSON no es predeterminado

¿Para qué? ¿Cuerpos de respuesta? Tener un tipo que cambia según un encabezado del remitente me parece arriesgado. Por ejemplo, podría terminar fácilmente con un código que funciona muy bien cuando la respuesta aparece como un objeto, pero si un atacante pudiera manipular los encabezados para cambiar eso a un formato binario, podrían suceder cosas malas.

sin codificación de cadena de consulta

Esto no es cierto. La API de búsqueda admite objetos de URL que admiten searchParams : https://url.spec.whatwg.org/#interface -urlsearchparams. Estos también se pueden usar como cuerpos de solicitud.

'buscar con el método POST', que es un modelo mental algo extraño

Es... cómo funciona HTTP. El nombre del método es una cadena.

Le pregunté al autor y principal proponente de Fetch, Jake Archibald

No soy el autor de fetch, aunque he contribuido. Tampoco sé qué me califica como el principal proponente.

La lista de "no me gusta" me parece bastante débil. Una mejor manera de probar esto podría ser con código. Ser agresivo y desinformado es una mala combinación, intenta sacudirte al menos uno de estos.

@joyeecheung

La única vez que me vi obligado a recurrir a XHR en el navegador fue cuando necesitaba progresar, aunque creo que con ReadableStreams del navegador es posible hacer lo mismo con una API que es un poco incómoda.

Actualmente es:

const response = await fetch(url);
const total = Number(response.headers.get('content-length'));
let bytes = 0;
for await (const chunk of iterateStream(response.body)) {
  bytes += chunk.length;
  console.log(bytes, ' - ', total);
}

Me gusta que esto sea explícito de que estás confiando en el encabezado Content-Length para el total. Aunque me gustaría presentar algún tipo de objeto observador para hacerlo más fácil. Y no necesitará iterateStream una vez que ReadableStream implemente Symbol.asyncIterator .

Además, la especificación de recuperación no parece incluir el tiempo de espera

Puede hacer esto con señales de cancelación:

const controller = new AbortController();
const { signal } = controller;
setTimeout(() => controller.abort(), 3000);
const response = await fetch(url, { signal });

Esto le da la flexibilidad de tiempo de espera de formas más complejas, por ejemplo, si no se envían bytes para algún tipo de tiempo de espera:

const controller = new AbortController();
const { signal } = controller;
let timeoutId;
const response = await fetch(url, { signal });
const resetTimer = () => {
  clearTimeout(timeoutId);
  timeoutId = setTimeout(() => controller.abort(), 3000);
};
resetTimer();

for await (const chunk of iterateStream(response.body)) {
  resetTimer();
  doSomething(chunk);
}

o agentes

Sí, no tenemos nada como esto todavía. Tendríamos que pensar en las implicaciones de seguridad de esto para la web. O simplemente reservamos esa opción para el nodo en la especificación, por lo que nunca usaremos algo con el mismo nombre para significar algo diferente.

(Volveré a abrir esto porque la discusión obviamente aún está en curso y este problema realmente no ha llegado a una conclusión hasta ahora).

@jakearchibald oh cielos, aquí vamos de nuevo.

Fetch admite el encabezado Content-Type.

Si. Eso no es lo mismo que usar un tipo de contenido: si acepto JSON, entonces dame JSON. No pida a todos los usuarios que lo decodifiquen manualmente.

¿JSON no es predeterminado para qué para qué? ¿Cuerpos de respuesta?

Tipo de contenido y acepta.

La API de búsqueda admite objetos de URL que admiten searchParam

Frio. ¿Está esto documentado para los usuarios? La única documentación de recuperación que he visto tiene personas que codifican manualmente cadenas de consulta y el enlace que acaba de proporcionar es una guía de implementación para desarrolladores de navegadores.

Es... cómo funciona HTTP. El nombre del método es una cadena.

No hace que sea 'buscar un GET' o como quieras decirlo menos incómodo. Más bien, alguien realmente quería usar el nombre 'buscar' en lugar de http.

Tampoco sé qué me califica como el principal proponente.

(Editar: se eliminó la mención del comportamiento de Jake en otras plataformas de redes sociales)

Una mejor manera de probar esto podría ser con código.

😂. Contribuiste a una especificación que no hace en 2018 lo que superagente hizo en 2012 y quieres código, como si nadie hubiera escrito antes un cliente HTTP que no apesta.

Este no es el lugar para discutir opiniones generales sobre la búsqueda en sí. Mantenga la discusión centrada en los méritos de implementar fetch en el núcleo.

Creo que esta es una API de DOM que será muy difícil de obtener correctamente en el núcleo (debido a las listas de seguridad de encabezados, etc.) pero fácil de obtener lo suficientemente bien en el espacio del usuario.

@benjamingr No creo que el nodo tenga que cumplir con las partes de fetch que existen para la seguridad web. Sería bueno obtener cambios en la especificación que permitan que el nodo haga eso sin dejar de ser compatible, siempre que no sea demasiado complicado.

@jasnell, mi principal preocupación es que agregar fetch al núcleo aún requeriría que los usuarios escriban un montón de código repetitivo para tareas comunes o instalen una biblioteca de alto nivel; como resultado, agregar fetch lograría muy poco para los usuarios finales.

@jakearchibald , siempre has estado muy dispuesto a dar un paso más para la plataforma web y, como sabes, yo también soy un fanático de la búsqueda :) Hay muchas cosas en la búsqueda que son muy diferentes del punto de vista de Node como cliente.

La superficie de la API de fetch es bastante grande y los navegadores (y los polyfills) realmente no la implementan. Si bien la búsqueda en sí misma ha sido bastante estable, los navegadores en realidad no lo han hecho:

  • Fetch introduce muchas clases (Solicitud, Respuesta, Encabezados, etc.) que existirían junto con la infraestructura existente del nodo para esas cosas.
  • Los navegadores aún no han descubierto .body.getReader() , funciona en Chrome y _sorta_ en Firefox detrás de una bandera. ¿Qué tipo devolvería en Node? ¿Es asyncIterable? ¿Qué hace .cancel en el cuerpo?
  • AbortController significaría discutir y establecer cómo funciona la cancelación en Node, compararlo con nuestros mecanismos de cancelación actuales, etc.

Las cosas que están orientadas a ServiceWorker no funcionarán (aunque no estoy seguro de si viste la nueva cosa de "trabajadores de servicio del lado del servidor" de Cloudflare, ¡que es realmente genial!).

Fetch es excelente, pero no estoy de acuerdo con que sea tan estable o esté listo en los navegadores como menciona la gente aquí: la mayoría de los polyfills ignoran descaradamente muchos de los casos extremos.

Lo peor: ambos sabemos que fetch es una API de nivel más bajo que XHR que es bastante más poderosa, se basa en mejores primitivas y agrega _capacidades_. Ninguno de los comentarios aquí se centró en eso: parece que las personas (aunque no los participantes del núcleo) quieren esto _como una conveniencia_ en lugar de con el objetivo directo de la compatibilidad de la plataforma del nodo web o las capacidades de exposición.

Creo que sería interesante hacer una _propuesta concreta_ evaluando todos los cambios que requeriría en Node y luego evaluarla.

@thecodingdude

Honestamente, no veo por qué esta discusión debe ocurrir en github; al menos, debe estar bloqueada para los colaboradores que van a trabajar en el código y las discusiones se centraron completamente en implementar fetch, idéntico al navegador donde sea posible, y nada más y nada menos.

Realmente no nos gustan los problemas de bloqueo aquí y solo lo hacemos cuando no podemos moderarlos. En este tema (aunque acalorado) la gente ha hecho un esfuerzo por ser cortés. Vemos a todos respondiendo o leyendo aquí como posibles contribuyentes y me gustaría invitar a cualquiera que esté leyendo esto y no esté seguro de cómo comenzar a participar más en el nodo para comunicarse (mi correo electrónico es benjamingr en gmail) y haremos nuestro mejor esfuerzo para encontrar formas interesantes de contribuir.

Hasta ahora, esta discusión ha ido bastante bien con personas que plantean argumentos a favor de ambos lados. Gracias por abrir el tema y traerlo aquí.


@mikemaccana Le pido que considere moderar este comentario.

oh querido, aquí vamos de nuevo.

He disfrutado de su perspectiva aparte de ese comentario en particular y solicito que mantengamos un ambiente de debate acogedor aquí, tanto como sea posible.

@benjamingr y @addaleax , envíen un nuevo problema con respecto a esta discusión. Nunca tuve la intención de abrir una lata de gusanos, lo que aparentemente sucedió y no me gusta el tono general y la actitud que @mikemaccana ha demostrado a lo largo de este número con repetidos comentarios fuera de tema y falta de ayuda general. Su condición de contribuyente debe ser reconsiderada.

Las discusiones acaloradas no son apropiadas para Node y la solicitud fue bastante simple: buscar en el núcleo. Me gustaría solicitarle que cierre/bloquee este problema y cree una propuesta si la inclusión es viable. No necesitamos 50 comentarios más discutiendo de un lado a otro, ya que terminamos sin ir a ninguna parte.

Creo que sería interesante hacer una propuesta concreta evaluando todos los cambios que requeriría en Node y luego evaluarla.

Eso prácticamente termina la discusión. Será mucho más fácil comprender la viabilidad cuando haya una propuesta (que es para lo que se diseñó node-eps, pero lamentablemente ya no sucede).

@thecodingdude De manera similar, no me gusta que no sea tolerante con la discusión sobre los méritos de incluir fetch y desee limitar la discusión solo a cómo debe hacerse, en lugar de si debe hacerse, lo cual es una preocupación razonable si usted personalmente te guste o no.

@benjamingr

Fetch introduce muchas clases (Solicitud, Respuesta, Encabezados, etc.) que existirían junto con la infraestructura existente del nodo para esas cosas.

Sí, no puedo ver cómo implementarías fetch sin implementarlos también. Node implementó la URL de WHATWG a pesar de tener sus propios métodos, así que supongo que sería lo mismo aquí. La pregunta es si vale la pena en este caso.

Los navegadores aún no han descubierto .body.getReader()

No creo que esto sea cierto. La especificación de transmisiones es bastante estable, con implementaciones en Chrome, Edge y Safari. Firefox aún no está allí, pero escuché que están finalizando su implementación.

¿Qué tipo devolvería en Node?

response.body tendría que ser un flujo legible de WHATWG (que es lo que quise decir en https://github.com/nodejs/node/issues/19393#issuecomment-376443373).

¿Qué hace .cancel en el cuerpo?

Esto está estandarizado. https://streams.spec.whatwg.org/#rs -cancel cubre las partes específicas de la transmisión, y la especificación de búsqueda reacciona a la cancelación en varios lugares.

AbortController significaría discutir y establecer cómo funciona la cancelación en Node

Sí, y AbortSignal es un EventTarget que supongo que debería ser un EventEmitter en el nodo. Ese es un problema de compatibilidad que realmente no podemos evitar en este momento.

Las cosas que están orientadas a ServiceWorker no funcionarán

¿Hay cosas en particular en las que estás pensando? Las referencias de Fetch al trabajador de servicio son bastante menores en comparación con CORS (para las que necesitaríamos encontrar soluciones).

Fetch es excelente, pero no estoy de acuerdo con que sea tan estable o esté listo en los navegadores

No creo que sea justo decirlo. Está implementado en Chrome, Firefox, Edge y Safari. Algunas implementaciones existen desde hace años. Ok, las transmisiones aún no son parte de la implementación de Firefox, pero es un caso atípico.

Creo que el "¿debería implementar el nodo?" La pregunta se reduce a compatibilidad e idoneidad en lugar de estabilidad. No tengo un sentimiento fuerte aquí, pero si dijo "El nodo implementará la búsqueda sin flujos, o los flujos de WHATWG pero no los obtendrá. Elija". Absolutamente elegiría las transmisiones de WHATWG.

Creo que sería interesante hacer una propuesta concreta evaluando todos los cambios que requeriría en Node y luego evaluarla.

+1 y los cambios requeridos en la especificación de recuperación.

@mikemaccana fetch es fetch: si no le gusta el estándar por algún motivo, hágalo con WhatWG, este no es el lugar adecuado para expresar sus quejas sobre lo que hace o no hace. Si esto realmente termina en el núcleo depende completamente de los desarrolladores de Node, quienes tendrán la responsabilidad de mantenerlo durante varios años; aquí es donde el 'espacio de usuario' puede ser más práctico porque está fuera del alcance de Node, así que si realmente estamos requiere _esta_ mucha discusión, entonces tal vez no sea un candidato adecuado para aterrizar en el núcleo.

¿Quizás sería tan amable de molestar a WhatWG con todos los problemas que ha discutido aquí y hacer que actualicen las especificaciones por usted? Puede presentar un problema con sus inquietudes aquí .

@thecodingdude Le pido amablemente que considere su redacción aquí. Como parte de Node, encontré la discusión (incluida la de Mike la mayor parte del tiempo) interesante. Sea respetuoso con los diferentes puntos de vista y experiencias y utilice un lenguaje acogedor e inclusivo .

Debatimos _mucho más_ que esto antes de presentar una característica como fetch , luego se presenta (como una propuesta concreta) al TSC, quien decide si vale la pena o no tenerlo en cuenta y luego hacemos _más_ discusiones sobre la implementación antes de aterrizarla.

@thecodingdude No se trata de quejas personales. Una vez más, me refiero al código repetitivo o las bibliotecas que la mayoría de los usuarios de nodos necesitarán instalar para usar fetch como un cliente HTTP. Como @Jamesernator ya mencionó, https://github.com/drufball/layered-apis/ es el lugar donde ya se está discutiendo sobre las API de alto nivel (gracias James). He dicho todo lo que necesito aquí en comentarios anteriores. Siento que continuamente los caracterizas erróneamente como agravios personales; si dejaras de hacerlo, no tendría que responder.

Aprecio que puede haber buenas razones para incluir cosas estándar, incluso si no son óptimas. Lo suficientemente justo. Pero los límites técnicos que requieren que la mayoría de los usuarios apliquen el mismo modelo no son quejas personales.

Editar: he utilizado medios técnicos para detener la discusión entre usted y yo.

Edite 2 para usar un lenguaje más acogedor según la solicitud de @benjamingr .

@mikemaccana , tal como está actualmente, su comentario viola nuestro código de conducta. Por favor, modere lo antes posible para cumplir con nuestros estándares .

@benjamingr Lo siento, y listo.

Fetch introduce muchas clases (Solicitud, Respuesta, Encabezados, etc.) que existirían junto con la infraestructura existente del nodo para esas cosas.

Estas son clases que Fetch necesitaría, pero también hay API que funcionan con Fetch que creo que los desarrolladores esperarían que estuvieran allí si Fetch se implementa en el núcleo. Estoy pensando en FormData y URLSearchParams, que son API útiles cuando se trabaja con datos de formulario y parámetros de URL. Los URLSearchParams ya están en el núcleo .

Si se va a implementar Fetch en el núcleo, ¿se esperaría que también se implementara FormData?

Me resultaría un poco extraño tener Fecth y URLSearchParams en el núcleo pero no en FormData.

Me he adelantado y he borrado los últimos comentarios. Las acciones de un individuo en las redes sociales no están dentro del alcance de nuestro rastreador de problemas. Le recomiendo encarecidamente que edite sus comentarios para mantener la discusión sobre el tema y constructiva.

Solo una pregunta: si el núcleo de Node obtiene un fetch global, ¿eso significa que podríamos implementarlo enviando node-fetch como una dependencia integrada, similar a lo que hacemos con node-inspect ?

@addaleax técnicamente sí, pero creo que una cosa que queremos hacer es mantener el código http subyacente separado, y por mi parte quiero implementar la mayor cantidad posible de forma nativa

Estoy de acuerdo con @devsnek . Además, node-fetch no parece integrar la prueba de la plataforma web en su conjunto de pruebas, las pruebas allí son lo suficientemente buenas para un paquete npm, pero si queremos ponerlo en el núcleo para el isomorfismo de la plataforma y afirmar la conformidad, en realidad probamos nuestra implementación con WPT. Sería mejor, incluso si necesitamos portar las pruebas para que puedan ejecutarse en un shell, y sospecho que necesitaríamos piratear algunas partes internas para que las pruebas funcionen como se espera.

@trygve-lie Probablemente también AbortController [*] y Blob .

[*] Dependiendo de lo que suceda con la propuesta de cancelación , podría ser otro CancelSignal o CancelToken o lo que sea. Personalmente, creo que sería una mala idea implementar DOM Events solo para obtener AbortController en Node, ya que entonces habría dos tipos de eventos distintos en Node.

Con respecto a los detalles de implementación, hay algunas cosas en las que pensar, derivadas de mi experiencia manteniendo la búsqueda de nodos y el trabajo tanto en el campo de la estandarización como en Node.js.

No deberíamos implementar partes de la API Fetch.

Creo que @jakearchibald ya ha tocado este punto. Los navegadores tienen un modelo de amenazas significativamente diferente al de Node.js y requieren muchas cosas que no tienen sentido en el entorno de Node.js. Algunos ejemplos incluyen:

Como corolario, solo un pequeño subconjunto de las pruebas de plataforma web es realmente aplicable a Node.js. Hay una gran cantidad de pruebas de plataforma web disponibles para Fetch , pero muchas de ellas se enfocan en las cosas que mencioné anteriormente que están fuera del alcance de una posible implementación de Node.js.

Web frente a Node.js

Response#body depende del estándar WHATWG Streams para la transmisión de datos (tanto de entrada como de salida). Francamente, los flujos web casi siempre están mejor diseñados que la infraestructura de flujos actual de Node.js; sin embargo, actualmente hay poco o ningún soporte de usuario para ello.Incluso el medio por el cual se implementa en Chrome se considera obsoleto ; y aunque el trabajo en la especificación continúa, ciertamente ya no está en su punto más activo . Esto plantea un dilema para una implementación de Node.js: implemente flujos web y arriesgue la consistencia y adopción de la plataforma, o use flujos de Node.js por Response#body (lo que hace node-fetch) y renuncie a la compatibilidad con los navegadores (posiblemente uno de las razones más importantes para agregar esta característica en Node.js en primer lugar). Sin embargo, existe un conjunto de utilidades de conversión no optimizadas entre flujos de Node.js y flujos web.

Eso sin mencionar la implementación de flujos web, que expone una superficie de API bastante pesada y plantea una complejidad adicional en el puente entre JS y C++, una rutina muy optimizada en los flujos existentes de Node.js.

Otros lugares donde existe el dilema Web vs. Node.js incluyen el uso de DOMException en abort fetch , EventTarget en AbortSignal , FormData , y el soporte para File API a través Blob (un tema que recuerdo que @jasnell me interesó).

JavaScript frente a C++

Esto se remonta a la pregunta planteada por @addaleax :

Si el núcleo de Node obtiene un fetch global, ¿significa eso que podríamos implementarlo enviando node-fetch como una dependencia incorporada, similar a lo que hacemos con node-inspect ?

La respuesta obvia en este caso sería "si usamos transmisiones web, comience desde cero y use C++; si seguimos usando transmisiones Node.js, continúe usando JavaScript". Pero antes de saltar a la primera opción, es importante recordar que, a pesar de sus muchas peculiaridades, nuestra implementación actual http está muy bien optimizada, y seguramente llevará muchas horas-humano obtener una limpieza tan limpia. implementación de la sala a la par con el rendimiento actual del módulo http .

Estoy a favor de tener esencialmente una copia en el árbol de node-fetch, tal vez con algunos ajustes específicos del núcleo. Pero me animaría y me ofrecería como voluntario para ayudar con cualquier experimentación con una versión de Web Streams.

Editar :Borrar declaraciones engañosas sobre el estándar Streams.

@TimothyGu Definitivamente creo que response.body ser un flujo de nodo sería una mala idea y generalmente anula el punto de compatibilidad como dices.

Sin embargo, podría darse el caso de que haya otra propiedad específica de Node response.readableStream que podría usarse si Node no quiere comprometerse con una implementación de transmisión completa de inmediato (o nunca). Mientras tanto, las personas podrían usar temporalmente una rama if simple, y si ambos tipos de ReadableStream obtienen Symbol.asyncIterator entonces tendrían al menos un método de consumo común.

Mientras tanto, las personas podrían usar temporalmente una rama if simple, y si ambos tipos de ReadableStream obtienen Symbol.asyncIterator, entonces tendrían al menos un método de consumo común.

Este ya es el caso con Node streams :)

@TimothyGu

Si bien el trabajo en la especificación [whatwg streams] continúa, ciertamente ya no está en su punto más activo.

Esto es bastante engañoso. La especificación es bastante completa para el conjunto de funciones que tiene, y el trabajo ahora se centra en crear flujos de transformación para exponer el comportamiento del navegador existente, por ejemplo, https://github.com/whatwg/encoding/issues/72.

La siguiente parte del trabajo en la especificación de flujos se centrará en la transferibilidad, de modo que los flujos puedan moverse entre los trabajadores. También estamos investigando activamente formas de exponer el analizador HTML de transmisión.

Hablando por al menos Chrome: el desarrollo de transmisiones es realmente importante para nuestros objetivos durante al menos los próximos años.

La gente de los nodos, la gente de los estándares web y la gente de los navegadores no están en planetas diferentes. Estamos bien aquí. Si le preocupa que se abandone un estándar, puede preguntar en lugar de adivinar usando las estadísticas de github.

@jakearchibald Ciertamente no estaba tratando de insinuar que el estándar Streams no se mantiene, sino para capturar el sentimiento de que pocas bibliotecas de usuarios están preparadas para lidiar con transmisiones web, lo que creo que es una caracterización justa del status quo. Disculpas por la interpretación engañosa de las estadísticas de GitHub.

@TimothyGu eso es justo. Creo que es porque solo estamos enviando flujos de transformación, que son esenciales para la OMI de la zona de usuarios.

Creo que es importante tener en cuenta que, como menciona Jake, la "gente de estándares" no vive en otro planeta, lo que significa que si un ecosistema tan grande como Node decidiera enviar una implementación fiel e interoperable de Fetch Standard, entonces sería razonable y Se espera que el estándar cambie y se adapte (con una flexibilidad razonable y luego de una discusión adecuada y exhaustiva) en áreas donde dichos cambios tengan sentido, siempre que no rompan o afecten negativamente el ecosistema de desarrolladores ya existente.

Como se ve en la evaluación exhaustiva de @TimothyGu , los mundos de los nodos y los navegadores ya divergieron bastante y esto continuará en el futuro a menos que se tomen medidas para hacer converger los dos mundos por el bien común. Esta convergencia tendrá que comenzar _en alguna parte_, y Fetch es una API popular y poderosa, que tiene mucho sentido en ambos mundos (por lo tanto node-fetch y todas las demás implementaciones de la misma). No creo que algunas clases y posibilidades globales (requeridas por la implementación) molesten a demasiadas personas, cuando no las usan, pero sin duda resultarán en una carga de mantenimiento y un trabajo de documentación ligeramente mayores, que deben ser evaluado cuidadosamente.
Sin embargo, mi corazonada aquí es que se beneficia de la convergencia de la plataforma y de facilitar la experiencia del desarrollador (desde un menor costo de cambio de contexto para desarrolladores de pila completa hasta la simplificación de Electron, IoT, renderizado del lado del servidor y otras bases de código donde coexisten los casos de uso de FE+BE) justificará este aumento del coste de mantenimiento.

En mi opinión, comenzar una implementación experimental/MVP de la API tendría mucho sentido incluso si eso significa algunas limitaciones y omisiones inicialmente (pero solo si esto no pone en peligro la implementación futura y el soporte para esas funciones omitidas). Esto requiere un MVP que se centre en la "compatibilidad web" futura, ya que claramente (y muchos lo han señalado antes que yo) el isomorfismo del software resultante y la consistencia multiplataforma son una de las mayores ganancias de la convergencia en Fetch.
A largo plazo, esto debería significar una convergencia en las estructuras subyacentes (como WhatWG Streams), pero este trabajo no necesariamente debe ser parte de las exploraciones iniciales.

Del mismo modo, no sería imposible (más bien, sería preferible) eventualmente instrumentar y/o refactorizar las pruebas WPT existentes relacionadas con Fetch para respaldar también el ecosistema Node. Una vez más, estos no son inamovibles, por lo que si se persigue la convergencia a largo plazo entre Node y el navegador, es posible cambiar estas pruebas de manera que satisfagan los requisitos de ambas partes.

Otra aplicación muy interesante de fetch in core es que, actualmente, al cargar WASM, se recomienda usar instantiateStreaming que se define específicamente contra un objeto Response siguiendo la especificación de fetch. ¡La carga rápida de ensamblaje web universal podría ser un aspecto interesante de esto!

Creo que es bastante revelador aquí que una de las primeras funciones implementadas en Deno es fetch global: https://github.com/ry/deno/blob/7762b55432ba73f07f90414aa7d023bb0779f5de/globals.ts#L52. Esto no es solo un "agradable tenerlo", sino una parte crítica de la historia.

@guybedford Creo que eso se debe a que deno se centra mucho en la semejanza del navegador... vea su compatibilidad con las URL HTTP en las rutas import . De hecho, para implementar import la forma del navegador, tendría que implementar Fetch Standard.

@guybedford eso es difícil de obtener : es solo una API muy básica que realiza llamadas HTTP, le faltan muchas de las capacidades que hacen fetch fetch y en su mayoría solo comparte el nombre.

¿Podemos por favor no empezar a comparar node.js con deno?

Hay una gran cantidad de valor en un proyecto experimental como deno en términos de lo que podemos aprender de él, lo que parece innecesario tratar de ignorar en general. No estoy de acuerdo con muchas de las suposiciones del proyecto (por ejemplo, las importaciones de HTTPS), pero en mi opinión, solo puede tener valor considerar ideas y puntos de vista de cualquier otro proyecto para inspirarse en Node.

Dado que este problema está cerca, estoy realmente confundido acerca de lo que haremos en el futuro.

¿Node implementará la API fetch o no?

Nos quedamos atrapados en una conversación interminable sobre preferencias personales sobre la especificación donde la mayoría de us solo quiere una API común entre el navegador y Node, también conocida como especificación fetch .

Tal vez sea un poco pragmático y mejore con el tiempo.

Mira estos números:

cross-fetch: 145,954 weekly downloads
isomorphic-fetch: 1,015,885 weekly downloads

El hecho de que tengamos 1 M (con la M grande) en isomorphic-fetch es el hecho de que todos necesitamos esto, y lo último que queremos es tener una discusión sobre la especificación.

Solo necesitamos la función, ya que 1 millón de descargas semanales muestran el hecho de que muchos códigos fuente hoy en día tienen que depender de esos paquetes que básicamente intentan solucionar este problema.

Sólo sé un poco pragmático.

Por favor.

El hecho de que tengamos 1 M (con la M grande) en isomorphic-fetch es el hecho de que todos necesitamos esto; y lo último que queremos es tener una discusión sobre la especificación.

1 millón de descargas es menos de lo que tengo en varios paquetes que ayudo a mantener (como bluebird o sinon), pero no tengo intención ni quiero seguir agregándolos al núcleo. Hay varias otras bibliotecas HTTP:

  • solicitud: 3.260.795 descargas semanales
  • axios: 835.153 descargas semanales

El hecho de que algo sea popular no indica que debamos agregarlo al núcleo (como lodash, request o express).

La principal motivación para agregar algo como fetch es la estandarización y no la popularidad :)

La principal motivación para agregar algo como fetch es la estandarización y no la popularidad :)
@benjamingr

Pero espero que no nos desviemos como ya lo hace este hilo en lugar de centrarnos en cómo podemos avanzar.

Sí, tienes razón, las descargas no significan que pertenecen a Node, pero justifican las necesidades de tener tal estandarización en Node. Sería tonto pensar lo contrario.

Mi problema es tener que confiar en paquetes de isomorphic-[insert name here for cross-platform package wanted] porque se cometió un error en 2009.

Y para otros que ya están criticando la conversación de Deno, aprendan de Deno los errores irreparables en NodeJS que ahora enfrentamos y el proyecto Deno está tratando de corregir (por alguna razón que desconozco, como un nuevo lenguaje de programación).

A menos que estemos dispuestos a introducir cambios importantes y tener una conversación al respecto, nos veremos obligados a repetir la historia.

No hace mucho tiempo, no se olvide de IO vs NodeJS, que fue uno de los mejores movimientos para que los más grandes de la comunidad unieran fuerzas, incluso cuando significaba tener diferentes direcciones en las Orgs, incluso cuando significaba tener un muchas piezas en movimiento.

Tal vez este problema y otros problemas que podría presentar el mismo fundamental issue son una señal de que NodeJS necesita una actualización de la arquitectura y la implementación.

Pero @benjamingr sí, tienes 100% razón.

porque se cometió un error en 2009.

Si se trata de buscar, el estándar de búsqueda solo comenzó a tomar forma alrededor de 2014, por ejemplo , este fue el compromiso que hizo que la devolución de la búsqueda fuera una promesa.

Tal vez este problema y otros problemas que podrían presentarse por el mismo problema fundamental es una señal de que NodeJS necesita una actualización en la arquitectura y la implementación.

Dudo que eso sea posible sin introducir problemas de compatibilidad: la refactorización se puede hacer con seguridad, pero la implementación actual debe permanecer y quedar obsoleta gradualmente, si son obsoletos (de lo contrario, habríamos podido deshacernos de new Buffer ahora que TypedArrays ha existido durante tantos años). Algunos usuarios pueden estar molestos por tener que aprender un conjunto de API de cosecha propia que es anterior a las contrapartes de la API web, pero habrá aún más usuarios molestos si su código actual deja de funcionar.

Dado que este problema está cerca, estoy realmente confundido acerca de lo que haremos en el futuro.
¿Node implementará la API de búsqueda o no?

Por lo que puedo decir, ninguna de las partes se convencerá mutuamente simplemente presentando el argumento de que cierta API es lo suficientemente popular como para estar en el núcleo, o que cierta API no está diseñada para servidores, por lo que no debería estar en el núcleo. . Hasta ahora, la nota de @TimothyGu en https://github.com/nodejs/node/issues/19393#issuecomment -376721984 me parece la sugerencia más viable, pero nada va a cambiar hasta que alguien abra un PR o publique una prueba de concepto, y tiene la determinación de hacer los cambios necesarios (incluso en la especificación y en la implementación y en el WPT) para que el resultado final sea razonable para Node, de modo que las personas que no lo quieren en el núcleo puedan estar convencido. Repetir los mismos argumentos que se han hecho varias veces en este repositorio probablemente no ayude a progresar, ya que el trabajo no se hace por sí mismo mágicamente, me temo, y AFAICT es mucho trabajo que realmente no puede forzar. cualquiera para ser voluntario.

En enero, axios tuvo 15 943 234, isomorphic-fetch tuvo 15 621 053 descargas y cross-fetch tuvo 2 444 751 de ellas.

Para ponerlo en perspectiva, el paquete react tiene 20,767,762 descargas.

Considere reabrir este problema, la búsqueda es una de las funciones más utilizadas en el nodo y ni siquiera está en el núcleo.

Puede ser bastante difícil resumir las partes en este hilo. Algunos no quieren fetch() porque tiene un nivel demasiado bajo, otros no lo quieren porque "las API de alto nivel se manejan mejor en el espacio del usuario".

¿Cómo puede ser tanto de bajo como de alto nivel?

Todos sus clientes HTTP populares favoritos, como axios y solicitudes, podrían construir fácilmente sus API existentes sobre este núcleo. ¿Por qué? Debido a que la estandarización significa que tenemos un núcleo mejor, y para aquellos que no desean funciones API de alto nivel, pueden usar ese núcleo.

El soporte HTTP/2 está aquí si quieres algo. https://github.com/grantila/fetch-h2

Me encanta que el JavaScript del navegador se estandarice en torno a un solo cliente HTTP, lo que hace que la creación de middleware sea mucho más fácil.

PHP tuvo que pasar por un laborioso diseño por comité para llegar a la estandarización y produjo varios PSR en el proceso: https://www.php-fig.org/psr/

Actualmente, Node tiene miles de millones de clientes HTTP diferentes, que solo funcionan con un puñado de middlewares, y hay varios paquetes de VCR con funciones débiles que se dividen entre solo 1 o 2 de estos clientes. Si pudiéramos estandarizar una implementación de fetch(), entonces se podría dedicar más trabajo a las herramientas que funcionan con este núcleo estándar, en lugar de distribuir el trabajo entre tantas soluciones diferentes específicas del cliente.

Los estándares son buenos, y poner la implementación estándar para actividades comunes, como hacer una solicitud HTTP en Node, les ahorraría muchos problemas a todos.

Creo que lo principal que falta aquí es alguien que realmente trabaje en ello. esta es una tarea probablemente medida en cientos de miles de líneas, y el nodo no tiene empleados como los navegadores para implementar esto.

¿No puede Node simplemente copiar y pegar la implementación desde un navegador como Chromium?

@sheerun no, no podemos, la infraestructura interna es muy diferente y también hay diferentes objetivos con las implementaciones. los navegadores tienen mucha indirección para asegurarse de que cosas como CORS no se infrinjan, pero el impl del nodo ni siquiera tendría CORS y probablemente querríamos centrarnos en el rendimiento.

Entonces, tal vez un mejor enfoque sería copiar y pegar polyfill como https://www.npmjs.com/package/node-fetch como API oficial y luego reescribirlo gradualmente con código nativo. Todo lo que a todos les importa es la forma estandarizada de realizar la recuperación de http en el nodo, no que se implemente de forma nativa en c ++.

El rendimiento es solo una consideración. Es importante, pero no el único. El otro problema es si Node.js puede implementarse con el cumplimiento de especificaciones adecuado. Como mínimo, también sería necesario implementar la API Streams y sería necesario analizar algunos problemas de estado global. Tengo una implementación que hice y elegí no continuar porque la impl no cumple completamente con la especificación debido a las adaptaciones necesarias para encajarla en Node.js

El subconjunto de fetch API probablemente también funcionaría. Entiendo que el 100 % de cumplimiento puede ser problemático, pero no creo que sea necesario para la mayoría de las aplicaciones (o incluso posible, simplemente no puede implementar algunas funciones como CORS porque no se aplican a este entorno).

Creo que el mejor enfoque sería decidir cuál es la "API común" de fetch , y luego divergir las implementaciones para el navegador (por ejemplo, se incluye CORS) y el nodo (por ejemplo, se implementa el búfer en lugar de las transmisiones). Todo el mundo debería estar bien siempre que Node no cambie la API fetch , sino que omita la implementación de algunas partes y también agregue alguna API adicional solo para nodos.

Tenga en cuenta que la API de node-fetch tampoco es 100% compatible con el navegador, pero es lo suficientemente buena para aplicaciones isomorfas y los desarrolladores no tienen problemas para usarla.

En cuanto a los tipos de Solicitud y Respuesta, el único campo que usa flujos es body , y la mayoría de la API no necesita flujos en absoluto. Creo que está bien si omite el soporte de este campo al menos para 1.0.

Para otro punto de datos, el proyecto Next.js está considerando seriamente agregar fetch automáticamente al tiempo de ejecución del servidor.

Serverless está desdibujando las líneas entre la ejecución de código en el servidor y el cliente. Cada uno de nuestros clientes instala Next.js, luego procede a traer isomorphic-fetch , node-fetch , fetch-h2 , etc.

En última instancia, es una pérdida de tiempo y recursos, y una gran fuente de problemas de seguridad, implementaciones incompletas y dispares, profundización del agujero negro de node_modules, etc.

Inicialmente estaba en contra de que fetch estuviera en Node.js, pero es hacia donde nos dirigimos inevitablemente. Incluso estaría feliz de ejecutar Chrome como tiempo de ejecución de mi servidor, ya que quiero más paridad de características entre las plataformas y una experiencia de desarrollador consistente :)

Inicialmente estaba en contra de buscar en Node.js, pero es hacia donde nos dirigimos inevitablemente. Incluso estaría feliz de ejecutar Chrome como tiempo de ejecución de mi servidor, ya que quiero más paridad de características entre las plataformas y una experiencia de desarrollador consistente :)

Tiendo a estar de acuerdo con esto cada vez más con el tiempo. Creo que debemos descubrir cómo conciliar EventTarget y EventEmitter y nuestras transmisiones con transmisiones web, que es el mayor bloqueador en mi opinión en este momento para obtener una abstracción similar a la búsqueda en Node.

Mi principal preocupación es que Node.js no es un navegador. Nunca tuvo las mismas garantías y el mismo nivel de aislamiento y seguridad del usuario que es parte de un navegador web. Esas compensaciones eran necesarias para proporcionar una plataforma del lado del servidor confiable y de alto rendimiento.

En un navegador, solo hay un único usuario. En Node.js, tenemos potencialmente decenas de miles. La API de recuperación está diseñada pensando en un solo usuario: utiliza el conjunto de conexiones del navegador, las configuraciones TLS, la configuración de mantenimiento, el almacenamiento en caché, etc. Soy firme al decir que no podemos implementar la especificación de recuperación completa, y terminamos arriba sería significativamente diferente del estándar para no ponerlo en un global.

Vale la pena señalar que AWS Lambda garantiza este 1-1 entre un proceso y un usuario. Tiene un costo elevado: las conexiones TLS no se mantienen abiertas y la latencia es mayor, entre otras cosas. (Otros entornos sin servidor no tienen la misma limitación).

Estoy de acuerdo en que deberíamos hacer algo al respecto y comenzar el proceso de construcción de un consenso sobre la búsqueda.

@joyeecheung ¿ es esto algo en lo que el equipo de estándares puede trabajar?

La implementación de la URL WHATWG de @mcollina Node tampoco está en el global, por lo que no creo que valga la pena preocuparse demasiado.

Creo que el mejor enfoque sería tener una API http.createFetch(opts) que envuelva el modelo de agente, http/https/http2/http3 de una manera que sea a) coherente con la API de Node.js b) compatible con las más comunes casos de uso para la especificación del navegador c) fácil de interceptar (nuestra API actual es extremadamente difícil de ajustar, consulte http://npm.im/nock).

Creo que esto podría darnos suficiente flexibilidad para resolver la mayoría de los casos de uso. Definitivamente habrá algunas diferencias clave en el nivel de semántica/comportamiento (almacenamiento en caché, agrupación de conexiones y seguridad) que me hacen preguntarme si deberíamos llamar a esto "buscar" para empezar; sin embargo, buscar es extremadamente popular y la comunidad está contenta con node. -fetch y otros polyfills, por lo que no me preocupa mucho tener algo significativamente diferente. Definitivamente necesitamos una nueva API de cliente HTTP en el núcleo, ya que nuestro modelo actual está envejeciendo mucho.

(Tenga en cuenta que también hay una diferencia significativa en la implementación de URL de WHATWG, y no estamos haciendo un buen trabajo al decir esto).

Actualmente, la búsqueda de WHATWG ignora el almacenamiento en caché, lo que, aunque me entristece, prefiero tener una API estándar sin almacenamiento en caché que ninguna API estándar.

--
phil esturión
@philsturgeon

El 26 de abril de 2019 a las 08:18, Matteo Collina [email protected] escribió:

Creo que el mejor enfoque sería tener una API http.createFetch(opts) que envuelva el modelo de agente, http/https/http2/http3 de una manera que sea a) coherente con la API de Node.js b) compatible con las más comunes casos de uso para la especificación del navegador c) fácil de interceptar (nuestra API actual es extremadamente difícil de ajustar, consulte http://npm.im/nock).

Creo que esto podría darnos suficiente flexibilidad para resolver la mayoría de los casos de uso. Definitivamente habrá algunas diferencias clave en el nivel de semántica/comportamiento (almacenamiento en caché, agrupación de conexiones y seguridad) que me hacen preguntarme si deberíamos llamar a esto "buscar" para empezar; sin embargo, buscar es extremadamente popular y la comunidad está contenta con node. -fetch y otros polyfills, por lo que no me preocupa mucho tener algo significativamente diferente. Definitivamente necesitamos una nueva API de cliente HTTP en el núcleo, ya que nuestro modelo actual está envejeciendo mucho.

(Tenga en cuenta que también hay una diferencia significativa en la implementación de URL de WHATWG, y no estamos haciendo un buen trabajo al decir esto).


Estás recibiendo esto porque comentaste.
Responda a este correo electrónico directamente, véalo en GitHub o silencie el hilo.

@philsturgeon

La búsqueda de WHATWG actualmente ignora el almacenamiento en caché

Eso es... incorrecto. Gran parte de la especificación y la API se dedican a negociar cachés.

¿Qué te hizo pensar que fetch ignora los cachés?

Lo siento, estoy hablando de mi parte trasera. Quise decir que la implementación de GitHub de fetch() (la que está en non como "node-fetch") ignora el almacenamiento en caché.

--
phil esturión
@philsturgeon

El 26 de abril de 2019 a las 09:33, Jake Archibald [email protected] escribió:

@philsturgeon

La búsqueda de WHATWG actualmente ignora el almacenamiento en caché

Eso es... incorrecto. Gran parte de la especificación y la API se dedican a negociar cachés.

¿Qué te hizo pensar que fetch ignora los cachés?


Estás recibiendo esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub o silencie el hilo.

+1 a un nuevo impl, tal vez incluso podamos usar napi para integrarlo en el núcleo

Estoy totalmente a favor de la venta en un módulo npm que luego exponemos como fetch , independientemente de si se trata de una nueva implementación o no.

@mcollina No creo que a nadie le preocupe la especificación de recuperación completa en términos de almacenamiento en caché. Node.js no es un navegador, pero cada vez se comparte más código entre el cliente y el servidor y, aunque no tenemos las mismas garantías, ya que nuestra superficie API se moderniza (como fs.promises), creo que buscar no encaja mal. Hace transmisiones bastante limpias, contrapresión, manejo de caché y otras cosas.

Hay partes que se ocupan de la política de origen cruzado que no necesitamos / queremos, pero aparte de eso, creo que hay mérito en una única primitiva moderna de bajo nivel para hacer solicitudes http en el núcleo (fetch es un nivel bajo primitiva para peticiones).

¿Qué tal algo como (y me estoy deshaciendo de la bicicleta):

  • Cree una subclase EventTarget de EventEmitter en el núcleo.
  • Cree una subclase de flujo WhatWG (o cerca de) de ReadableStream.
  • Explícitamente no admite blobs (¿pero quizás lo agregue más tarde?).
  • Agregue fetch como experimental en la parte superior de http.

Soy bastante firme en no tener un solo grupo de conexión global, configuraciones de seguridad, almacenamiento en caché, etc. Estoy de acuerdo con su plan siempre que podamos crear todo eso y desmantelarlo si queremos. Node.js se volvió extraordinariamente mejor ya que eliminó el agente global predeterminado, y realmente no quiero que esa situación vuelva a suceder.

(menos algunos detalles sobre la interoperabilidad de flujos, pero esos son detalles de la API).

Por un lado, me encantaría ver a Fetch en el núcleo de nodejs.
Por otro lado, creo que la gente debería moderar sus expectativas, ya que sospecho que el resultado final va a decepcionar a muchos usuarios.

Razones:

  • Las personas que buscan soporte nativo para Fetch quieren usarlo en un entorno isomorfo: es decir. quieren escribir el mismo código y ejecutarlo en navegadores, nodejs e incluso react-native.
  • Incluso si omitimos temas como cookie , cache , protocol-relative url y error handling , aún existe el problema con WHATWG Stream.
  • Mi gran preferencia es que nodejs implemente Fetch con WHATWG Stream, pero eso significa que la API no funcionará con la mayoría de las bibliotecas existentes (claro, puede convertirlas en flujo de nodejs, pero el paso de interoperabilidad en sí no es isomorfo).
  • Por otro lado, con la implementación múltiple de Fetch usando el flujo de nodejs, no veo el motivo de otro Fetch que sea inherentemente no isomorfo. (Ni siquiera podemos ponernos de acuerdo en cosas simples como highWaterMark , que hacen que el código funcione bien en los navegadores, pero se enfrenta a una contrapresión en nodejs).
  • Insto a la gente a leer las limitaciones de las implementaciones de Fetch existentes, así como lo que tuvimos que hacer para hacer que Fetch sea más aceptable en el lado del servidor, luego considere si este es el Fetch que desea.

https://github.com/bitinn/node-fetch/blob/master/LIMITS.md

@bitinn, ¿qué pasa con una subclase de flujo de nodo que implementa la interfaz de flujo whatwg?

¿Qué importancia cree que tienen aquí las URL relativas de cookies/caché/protocolo? Creo que el manejo de errores y las secuencias se pueden resolver y las secuencias de Node ya son asíncronas de todos modos :)

@benjamingr Ese podría ser un buen compromiso.

Ventajas:

  • Las personas que solo quieren un Fetch unificado que abstraiga la diferencia H1/H2 estarán felices, no necesariamente usan Fetch en un sentido isomórfico, pero les gusta el hecho de que la API funciona de manera similar, por lo que hay menos cosas que aprender y dominar.
  • Tener Fetch API en el nodo, incluso uno limitado, moverá la infraestructura circundante, por lo que el código relacionado con HTTP se volverá más isomorfo con el tiempo.

Contras:

  • Las personas que usan Fetch API en un sentido isomórfico exigirán más que solo fetch() : para empezar hay new Response() , new Request() , new Headers() , Blob , FormData , AbortSignal , entonces la falta inherente de cache y cookie hará que las personas escriban código no isomórfico.
  • Las personas que desean más control que la recuperación estándar exigirán más que solo fetch() : para comenzar, deberán usar agent personalizados, luego habrá cosas como controlar el tamaño de la descarga, lidiar con una respuesta infinita, soporte de enchufe, etc.

Fetch API está diseñado para hacer algunas cosas muy bien, pero no otras. Mover las especificaciones en esas direcciones será difícil, por lo que casi siempre tendrá que hacer juicios que alienen a las personas.

Vea nuestras pruebas (que son 2700 líneas, cuando el código real tiene solo 500 líneas):

https://github.com/bitinn/node-fetch/blob/master/test/test.js

Vea también cómo el manejo de errores no es trivial dada la especificación Fetch existente:

https://github.com/bitinn/node-fetch/issues/549

@bitinn , ¿vas a asistir a la cumbre (https://github.com/nodejs/summit/issues) por casualidad? Creo que sería genial hablar de esto con otras partes interesadas (como @mcollina y tal vez @jakearchibald si asiste) y enumerar los desafíos para agregar fetch al núcleo.

cc @nodejs/estándares abiertos

También me gustaría agregar que contribuir a la especificación de búsqueda en el pasado fue una experiencia agradable y que las personas que trabajan en la búsqueda son muy amables y cordiales, por lo que definitivamente creo que debemos involucrar a esas personas al hacer esto.

Creo que sería importante que Node se asegure de que no se comporte de manera diferente cuando se usan opciones no predeterminadas con fetch .

Por ejemplo, tome las credenciales (cookies), suponiendo que Node no se envió con soporte de credenciales, entonces mi opinión sería que sería mejor para Node arrojar un error en fetch(someUrl, { credentials: 'include' }) en lugar de ignorar silenciosamente la opción de credenciales. En su lugar, Node introduciría su propia nueva opción, por ejemplo 'bypass' y usaría fetch(someUrl, { credentials: 'bypass' }) (nombre de cobertizo para bicicletas).

Ahora, obviamente, sería un gran dolor tener que hacer fetch(someUrl, { credentials: isNode ? 'bypass' : 'omit' }) , en su lugar, uno podría decir que cualquier opción que no se proporcione solo usará el valor predeterminado del host, que en el caso de Node sería 'bypass' . Aún mejor sería si la especificación de recuperación en sí misma pudiera reflejar que las implementaciones de recuperación que no son del navegador pueden usar diferentes valores predeterminados para varias opciones.

Del mismo modo, creo que es muy importante que si Node va a divergir con la especificación de una manera no compatible (por ejemplo, para exponer datos adicionales o similares), debería hacerlo usando nuevas propiedades en lugar de comportarse de manera diferente a las propiedades existentes.


En mi opinión personal, incluso podría valer la pena considerar características como cookies/CORS/cachés/etc dentro de Node (si se proporciona una búsqueda global con estas características o no, personalmente no me importa).

Por ejemplo, Node podría considerar una fábrica con cosas como tarros de galletas y similares a otras bibliotecas http:

import { makeFetch, createPersistentCookieJar, createInMemoryCache } from 'fetch'

const cache = createInMemoryCache({ limit: os.totalmem() / 4 })
const cookieJar = createPersistentCookieJar('./cookies.cookiejar')

const fetch = makeFetch({ cache, cookieJar, origin: 'https://mycoolwebsite.com' })

// Use fetch like a browser fetch

Habiendo dicho eso, sigo pensando que sería mucho mejor para Node tener un buen subconjunto de recuperación que no implementarlo todo o retrasarse por mucho tiempo trabajando en una implementación completa.

Por ejemplo, tome las credenciales (cookies), suponiendo que Node no se envió con soporte de credenciales, entonces mi opinión sería que sería mejor para Node arrojar un error en fetch(someUrl, { credentials: 'include' }) en lugar de ignorar silenciosamente la opción de credenciales.

No estoy muy seguro. En el navegador, si llama a fetch(someUrl, { credentials: 'include' }) cuando no hay credenciales (nueva visita al sitio, modo de incógnito, cookies recién borradas), no se rechaza.

Parece que Node debería comportarse como un navegador sin credenciales.

En su lugar, Node introduciría su propia nueva opción, por ejemplo 'bypass' y usaría fetch(someUrl, { credentials: 'bypass' }) (nombre de cobertizo para bicicletas).

¿Cómo diferiría esto de 'omitir'? No creo que Node deba agregar nuevas opciones sin agregarlas a la especificación.

@jakearchibald Creo que me estaba confundiendo con CORS cuando intentaba hacer un ejemplo, mi ejemplo debería haber sido fetch(someUrl, { mode: 'bypass-cors' }) donde ignoramos completamente CORS pero aún podemos leer la respuesta ya que este es el comportamiento típico que la mayoría de la gente quiere en Nodo.

Obviamente hay alternativas:

  • Simplemente permita leer respuestas normalmente opacas en Node (tratando file:/// como el origen)
  • Agregue otro mecanismo solo para Node para leer respuestas opacas (tratando file:/// como el origen)
  • Simplemente ignore todas las banderas relacionadas con cors y lea cualquier respuesta

Preferiría inclinarme por el lado de la precaución e ir con cualquiera de las tres primeras ideas y no solo ignorar las banderas existentes (en lugar de usar cosas que el nodo no quiere admitir como no-cors o realmente admitir ellos)

Para @Jamesernator y otros que lean este hilo.

La parte difícil de hacer que Fetch se acerque lo más posible a las especificaciones es la falta de context , en los navegadores lo das por sentado: cookies , cache , sessions pueden considerarse parte de él.

Esta es probablemente la razón por la que fetch-h2 inventó su objeto de contexto, porque es más natural para HTTP/2.

Esta es también la razón por la que node-fetch no lo hizo, porque nos gusta el hecho de que nodejs HTTP/1 no tiene contexto, y usted controla las conexiones a través de agent personalizados.

Mi opinión : las cosas serán más fáciles si nodejs puede proporcionar una nueva capa de abstracción HTTP en la que no piense en HTTP/1 o HTTP/2; sí, es tan difícil como escribir un Fetch que cumpla con las especificaciones, pero no es necesario que cumpla con las especificaciones cuando invente una nueva API, _puede retrasar de manera efectiva el paso de cumplimiento cuando envuelva esta API en Fetch._


El segundo problema es simplemente API, puede hacer cosas como new Response(new FormData()).Blob() y, según las especificaciones, debería funcionar.

Mi opinión : las cosas serán más fáciles si nodejs puede proporcionar cosas como Blob , FormData y WHATWG Stream en primer lugar. Sin ellos, confía en el espacio del usuario para implementar una solución compatible, pero ni Blob ni FormData exponen una forma de "detectarse" a sí mismos de manera confiable, por lo que confía en la adivinación de nombres y la tipificación de API. (Esto es lo que hace node-fetch ).


El tercer problema es el cambio de especificaciones. Hubo casos en los que el cambio de especificación de Fetch interrumpe la API existente. Por ejemplo, leer los encabezados Set-Cookie sigue siendo un truco en node-fetch porque la API Headers espera que get(name) sea una sola cadena, cuando puede tener varios Set-Cookie encabezados.

Los navegadores no tienen que preocuparse por esto debido a su context (solía haber getAll() pero esta API se eliminó), la especificación nunca tuvo que moverse y agregar una API adicional.

Mi opinión : si nodejs muestra oficialmente la intención de implementar Fetch, entonces tengo la sensación de que el equipo de especificaciones de Fetch podría estar convencido de agregar una API especial para cosas como Set-Cookie (salvo el problema de seguridad). Esto podría extenderse a otros dilemas relacionados con las especificaciones.

Gracias por leer.


@benjamingr Lamentablemente, no voy a ir a la cumbre (hoy en día trabajo principalmente en C#), pero espero que el equipo de nodejs discuta este problema con el equipo de especificaciones de recuperación y los proveedores de navegadores.

Tal vez sería mejor cambiar las tornas y en lugar de tratar de hacer coincidir al 100 % la especificación oficial fetch , crear la propia especificación de fetch del nodo que tiene un alcance más simple que el fetch original y también es extremadamente simple de polillenar con fetch original (idealmente API 1:1). Con este cambio, no necesita exponer fetch global o Request o Response porque ya no está tratando de implementar el fetch original.

Una API podría verse así:

const { fetch, Response, Request } = require('http')

Y en el lado del navegador se transformaría en algo como:

const { fetch, Response, Request } = window

Hablé con @jakearchibald en privado (preguntando sobre la cumbre) y dado que muchas de las partes involucradas no asistirán, estaba pensando en convertir esto en un pequeño equipo de partes interesadas.

@jakearchibald @bitinn y cualquier otra parte que pueda estar interesada: creo que esto vale la pena y creo que deberíamos discutirlo. Creo que principios de junio (después de la JSConf y la cumbre) sería un buen momento para discutir esto.

@nodejs/estándares abiertos wdyt?

@sheerun sobre tu comentario,

Preferiría que pusiéramos esas cosas en el objeto global para que no necesitemos crear casos especiales a menos que haya una razón técnica para ello (no me importa volver a exportar cosas).

const { fetch, Response, Request } = globalThis; // don't forget that we have this now

Si va a haber diferencias de implementación, un enfoque de módulo tiene más sentido como lo describe @sheerun , ya que se puede diseñar una corrección de compatibilidad del navegador para el caso de Node, al igual que con los trabajadores.

@yordis Es solo un ejemplo. Estoy bastante seguro de que la cuña no sería tan simple y más bien algo así como:

const { fetch, Response, Request } = __makeNodeFetch();

donde __makeNodeFetch es inyectado por polyfilling bundler / library

EDITAR: También sugeriría que el equipo del nodo envíe el calce oficial en lugar de que lo cree un tercero

Oye, solo una actualización de que tuvimos una reunión sobre esto en la cumbre y aquí están las notas https://docs.google.com/document/d/1tn_-0S_FG_sla81wFohi8Sc8YI5PJiTopEzSA7UaLKM/edit también está el PR vinculado arriba que está en una etapa muy temprana.

Necesitamos activamente personas que den un paso adelante y ayuden con los problemas anteriores.

@benjamingr pregunta por ignorante.

¿Qué tan difícil sería adaptar la implementación de Deno de fetch en NodeJS? (por favor, no se concentre en Deno vs NodeJS 🙏)

Mirando el código, parece que podría ser portátil, pero no estoy seguro de las paredes a las que me enfrentaré al hacerlo.

¿Alguien intentó eso?

¿Deberíamos intentar eso?

¿Qué tan difícil sería adaptar la implementación de fetch de Deno en NodeJS?

Muy, la implementación de Deno es muy incompleta y carece de muchas funciones. Comenzar desde la búsqueda de nodos como este PR ya tiene muchas más funciones completas. Además, la implementación de Deno funciona conectándose a tokio con flatbuffers (no usamos ninguno) y realmente no tendría mucho sentido para node.

(No hay enemistad entre Deno y Node.js, realmente no es una competencia :))

No puedo imaginar cómo alguien va a leer todos los comentarios en este hilo y tomar una decisión. Está claro que es bueno tener un debate público sobre esto, pero también está claro que es prácticamente imposible llegar a un consenso. Me imagino que el equipo central leerá algunos (o la mayoría) de los comentarios y tomará sus decisiones.

comentario de @bitinn :

El tercer problema es el cambio de especificaciones. Hubo casos en los que el cambio de especificación de Fetch interrumpe la API existente. Por ejemplo, leer los encabezados de Set-Cookie sigue siendo un truco en la búsqueda de nodos porque la API de encabezados espera que get (nombre) sea una sola cadena, cuando puede tener varios encabezados de Set-Cookie.

Acabo de abrir https://github.com/whatwg/fetch/issues/973 para comenzar la discusión nuevamente sobre getAll .

Además, fetch ha filtrado la respuesta donde se ocultan algunos encabezados. Lo que no hace que obtenga un cliente HTTP con todas las funciones por especificación.

Desde la perspectiva del desarrollo, introducir la búsqueda nativa no es una buena idea. Y el rendimiento no es realmente un argumento para ello.

Pero el soporte de la misma api ( fetch ) para el navegador y el backend de la misma manera (sin dependencia externa) sería una victoria para el ecosistema JS/TS por completo.

@gkatsanos hemos discutido esto en la cumbre de mayo/junio: esto es lo que se bloqueó en https://docs.google.com/document/d/1tn_-0S_FG_sla81wFohi8Sc8YI5PJiTopEzSA7UaLKM/edit?usp=sharing

En mi opinión, la verdadera victoria para la web, si el nodo fuera a buscar, en realidad sería que de repente hay un mecanismo de cancelación ubicuo a través AbortSignal . RxJS aprovecharía eso de inmediato. Otras bibliotecas ya han comenzado a utilizarlo.

Me encantaría esto también.

no me gusta distinguir el navegador y el nodo,
esos son ecmascript (o digamos javascript) que son de C ++ en la parte inferior, al igual que esos son bebés de la misma madre. No me gusta ver pelear a los bebés. debemos darles el mismo amor.
no importa qué api, podemos estandarizarlo.

La situación con fetch in core no ha cambiado. Hay muchos a los que les gustaría tenerlo, pero hay una serie de desafíos técnicos muy no triviales que lo hacen difícil, uno de los cuales es el hecho de que, para ser compatible con la implementación en los navegadores, el núcleo primero necesitaría una implementación de la API de flujos del navegador, que es (en muchos sentidos) incompatible con los flujos existentes del núcleo y necesitaría implementarse desde cero para tener un buen rendimiento. También hay problemas relacionados con la forma en que fetch usa el estado global interno, que funciona bien en un proceso de navegador pero no tan bien en el lado del servidor. Sí, hay implementaciones como node-fetch que se acercan pero que no cumplen totalmente con las especificaciones (por ejemplo, en su lugar usa flujos de Node.js). Estos no son problemas imposibles de resolver, por supuesto, solo necesitan a alguien dispuesto a dedicar tiempo y esfuerzo para implementarlo y llevarlo a través del proceso para aterrizar. Si bien personalmente no veo la necesidad de buscar en el núcleo, estoy feliz de trabajar con cualquiera que esté dispuesto a dedicar tiempo.

Si alguien quiere recoger esto: https://github.com/nodejs/node/pull/22352

Estos no son problemas imposibles de resolver, por supuesto, solo necesitan a alguien dispuesto a dedicar tiempo y esfuerzo para implementarlo y llevarlo a través del proceso para aterrizar.

Creo que un buen primer paso sería incluir solo partes de fetch, a saber:

  • EventTarget (o una API compatible con EventTarget)
  • AbortController (https://github.com/openjs-foundation/summit/issues/273 por cierto)
  • Eventualmente: buscar

Creo que los flujos se pueden manejar a través de Symbol.asyncIterator: llevar los flujos whatwg al núcleo sería una tarea enorme y tendría que hacerse con mucho cuidado.

Estoy entusiasmado con EventTarget y AbortController en el núcleo de Node, que parecen pasos importantes en el camino, pero hay algunos más.

@mcollina ha articulado un plan para eventualmente mover los flujos de WHATWG al núcleo, basado en la interoperación con iteradores asíncronos y la creación de prototipos en un módulo de usuario. Soy optimista de que, si alguien se esfuerza, ¡esto será posible! Veo esto como un requisito previo alcanzable para obtener en el núcleo, además de lo que menciona @benjamingr , si la compatibilidad con la semántica web es un objetivo.

Otro posible aspecto de buscar en el núcleo (que @mcollina ha enfatizado) es una especie de "API de agente de usuario" para explicar cómo funcionarían cosas como las cookies, el almacenamiento en caché y posiblemente el proxy. La capacidad de búsqueda de los navegadores se basa directamente en un agente de usuario incorporado, sin capacidades completas para manipularlo, por ejemplo, alternando entre diferentes perfiles. Es posible que se necesite algo más para entornos de servidor.

Creo que ambos son factibles, si alguien es capaz de realizar (una gran cantidad de) trabajo. Mi compañero de trabajo @ptomato en Igalia está comenzando con AbortController, basado en el patrocinio de Bloomberg, consulte https://github.com/nodejs/node/issues/31971.

¡Estoy particularmente entusiasmado con las transmisiones de WHATWG que aterrizan en el núcleo! Gracias a todos los que trabajan en todas estas cosas.

  1. También estoy emocionado, ¿podemos tener una hoja de ruta?
  2. por cierto, desde el principio, ¡no separe el navegador (o algo así) y la API del servidor para la misma función! esos son solo un "agente de usuario". a los clientes no les importa qué navegador, qué servidor, qué API usas.
  3. Realmente quiero contribuir, pero no escribo C++, ¿puedes enseñarme?

Otro posible aspecto de buscar en el núcleo es una especie de "API de agente de usuario" para explicar cómo funcionarían cosas como las cookies, el almacenamiento en caché y posiblemente el proxy. La capacidad de búsqueda de los navegadores admite esto directamente, sin capacidades completas para manipularlo, por ejemplo, alternando entre diferentes perfiles. Es posible que se necesite algo más para entornos de servidor.

En realidad, es el punto que más espero, así que puedo ver si puedo copiar el enfoque para nuestro lenguaje de script CMS.

Un agente también podría ser el punto en el que decidiría cómo manejar la autenticación HTTP (que el navegador también haría de forma nativa para, por ejemplo, la autenticación básica de http) y quizás incluso cómo y si reutilizar las conexiones HTTP (necesario para la autenticación NTLM que funciona en la conexión nivel).

@jakearchibald lentamente:] Primero AbortController, tendría que haber una cantidad significativa de trabajo realizado antes de que whatwg-streams llegue al núcleo. Presumiblemente, fetch aterrizaría con soporte de iterador asíncrono y no con flujos whatwg.

Para aquellos que deseen trabajar en esto, les sugiero la siguiente estrategia que he usado para desarrollar otras características nuevas importantes:

  1. Cree una bifurcación separada de nodejs/node (como lo hice para el trabajo de http2 y quic... por ejemplo, https://github.com/nodejs/quic) y haga el trabajo en la función de forma aislada allí. Esto permitirá que el trabajo avance mucho más rápido. Una vez que se alcancen los hitos clave, abra relaciones públicas para fusionar esas cosas con el núcleo.

  2. Se paciente. Cuando llega el momento de abrir esos RP para fusionar cosas en el núcleo, puede haber muchos comentarios/discusiones/solicitudes de cambio. Esos pueden tomar algún tiempo para pasar, especialmente con grandes cambios.

  3. No descarte la posibilidad de vender en dependencias existentes. Es posible que no necesitemos escribir todo desde cero. Las razones clave por las que nos gustaría escribir algo desde cero son (a) si podemos lograr un rendimiento significativamente mejor, (b) para lograr una mayor paridad y coherencia con la API de Node.js existente, o (c) para lograr un mejor cumplimiento de las especificaciones.

  4. Tenga en cuenta que agregar un nuevo módulo de nivel superior o global siempre es importante en Node.js y que todo lo que se haga aquí será un estado experimental durante algún tiempo. Aunque las funciones experimentales no están sujetas a las mismas reglas de semver, a menos que la función esté detrás de un indicador de compilación o tiempo de ejecución, el PR que agrega la función inicial sigue siendo semver-minor o semver-major dependiendo de cómo se haga. Esto es importante porque las adiciones semver-major, incluso las experimentales, no se pueden transferir a versiones anteriores a menos que esas backports se realicen de manera semver-minor (por ejemplo, no podemos agregar un nuevo módulo de nivel superior o global a 13.x, 12.x , o 10.x). Esto es importante porque cosas como fetch y AbortController son globales en el navegador y agregarlos como globales en Node.js sería muy importante.

  5. El sesgo para la implementación de Node.js siempre debe ser adherirse a la especificación estándar y la compatibilidad lo más cerca posible. Deberíamos minimizar absolutamente la cantidad de detalles específicos de Node.js que los desarrolladores deben tener en cuenta (es decir, minimizar el "Funciona de esta manera en los navegadores, pero de esta otra manera en Node.js") sin una justificación sólida. En caso de duda, debe cumplir con las especificaciones.

4. Tenga en cuenta que agregar un nuevo módulo de nivel superior o global es _always_ semver-major en Node.js

¿Eso significa que las actualizaciones de V8 que agregan nuevos globales siempre son importantes y no se pueden adaptar?

por cierto, desde el principio, ¡no separe el navegador (o algo así) y la API del servidor para la misma función! esos son solo un "agente de usuario". a los clientes no les importa qué navegador, qué servidor, qué API usas.

Realmente quiero contribuir, pero no escribo C++, ¿puedes enseñarme?

No podemos enseñarle C ++, pero hay muchos lugares para contribuir a buscar en el núcleo, muchas tareas de investigación y JavaScript.

Le invitamos a participar (hay una sesión en la cumbre sobre AbortController en el núcleo) y ponerse al día con la última sesión https://docs.google.com/document/d/1tn_-0S_FG_sla81wFohi8Sc8YI5PJiTopEzSA7UaLKM/edit?disco= AAAAGdykWVg&usp_dm=true&ts=5eaa5dc3

¿Eso significa que las actualizaciones de V8 que agregan nuevos globales siempre son importantes y no se pueden adaptar?

Esa es un área totalmente gris, para ser honesto :-) ... específicamente, los cambios de Node.js que agregan nuevos globales siempre son muy importantes

Realmente quiero contribuir, pero no escribo C++, ¿puedes enseñarme?

Con respecto a buscar, realmente no debería haber una razón para tocar c ++ ya que toda la API puede existir en la capa de JavaScript. De hecho, una implementación adecuada en el núcleo deberá abarcar y abstraer las API http/1, http/2 y, finalmente, http/3 para que funcionen de forma coherente y correcta, todas las cuales están expuestas en el nivel de JavaScript.

Creo que podríamos respaldar un nuevo módulo o un nuevo global a las líneas de lanzamiento existentes, si requiere que se habilite un indicador de línea de comando

Otro posible aspecto de buscar en el núcleo (que @mcollina ha enfatizado) es una especie de "API de agente de usuario" para explicar cómo funcionarían cosas como las cookies, el almacenamiento en caché y posiblemente el proxy. La capacidad de búsqueda de los navegadores se basa directamente en un agente de usuario incorporado, sin capacidades completas para manipularlo, por ejemplo, alternando entre diferentes perfiles. Es posible que se necesite algo más para entornos de servidor.

Esencialmente, esta es mi principal objeción para tener una búsqueda completa que cumpla con las especificaciones en el núcleo. Podemos implementar algo "similar a la búsqueda", pero las partes de almacenamiento en caché y seguridad son extremadamente difíciles y posiblemente ni siquiera se deseen en el lado del servidor. O potencialmente lo son, pero necesitarán una API diferente para estar expuestos.

Para recapitular todo lo anterior, fetch() asume que solo hay un usuario para toda la máquina virtual de JS. Node.js no puede (y no debe) hacer esta suposición. node-fetch tampoco hace esa suposición y funciona extremadamente bien en Node.js debido a eso. No creo que podamos cumplir con las especificaciones en este caso.

Como dije varias veces, estoy dispuesto a apoyar a cualquiera que esté dispuesto a realizar este gran esfuerzo.

Obviamente, tienes muchas palabras. porque dice algo que simplemente se basa en el estándar existente, y el equipo de nodejs necesita más colaboración con el equipo de whatwg. desde la vista de historial, primero el navegador, luego el nodo. nodo, desde el principio, no se ajusta al estándar web para diseñar api, ¡así que el nodo tiene mucho dolor!

  1. ¿Por qué no renunciar a la compatibilidad innecesaria? @jasnell
  2. ¿Por qué no rediseñar el estándar de recuperación para que se ajuste a los casos de uso del navegador y del nodo? @jakearchibald
  3. ¿Por qué no implementar EventTarget?
  4. reviso los documentos del módulo http, https, http2 del nodo que dicen que el nodo almacena en caché las solicitudes/respuestas HTTP, por qué su documento de Google dice que el nodo no almacena en caché las solicitudes/respuestas HTTP

La compatibilidad no es innecesaria. ¡Sin él, no hay ninguna razón real para implementar esto en el núcleo! Podríamos simplemente dejar que los usuarios implementen sus propias versiones incompatibles. Además, dado que fetch se usa en producción, whatwg no puede y no lo hará simplemente rediseñarlo. La implementación de EventTarget es razonable, pero la pregunta sigue siendo si deberíamos hacerlo dado que ya tenemos EventEmitter.

En cuanto al almacenamiento en caché, Node.js no implementa ninguna parte del almacenamiento en caché de http.

  1. tarde o temprano, debería renunciar a la compatibilidad, como el propio nodo tiene soporte LTS.
  2. ¿Te has comunicado con el equipo de whatwg?
  3. desde la vista del nodo, implementar el estándar es más fácil que el navegador. debido a que el nodo es solo un tiempo de ejecución, no como un navegador, ¡los clientes no siempre están dispuestos a actualizar su navegador!
  4. EventEmitter no es tan sorprendente pero innecesario en comparación con EventTarget.

Este es el problema heredado de la historia del nodo en sí. porque el nodo no se ajusta al estándar para diseñar la API desde el principio.

Muchas de las personas que trabajan en node.js también están involucradas con organismos de estándares, incluido WHATWG. Este problema se trata de agregar búsqueda, no cualquier API de http aleatoria, por lo que creo que tiene sentido analizar el alcance de la discusión aquí para cumplir con la búsqueda.

Si lo piensa, el gran paquete request solo existe porque el uso del módulo HTTP incorporado requería demasiado repetitivo. Veámoslo también de esta manera:

  • Navegadores: XMLHttpRequest -> buscar
  • Node.js: http/https/http2 -> buscar?

La API de recuperación se creó como una forma más fácil de realizar solicitudes web en el navegador, que reemplazó a XMLHTTPRequest . La misma API debe usarse como reemplazo de http , https y http2 en Node.js.

@Richienb

La API de recuperación se creó como una forma más fácil de realizar solicitudes web en el navegador, que reemplazó a XMLHTTPRequest.

En realidad, IIUC fetch se creó como una _API de nivel inferior_ en navegadores con _más capacidades_ y no como una API de nivel superior que es ergonómica. Fetch facilita la transmisión de respuestas y hace cosas de bajo nivel como el HTTP integrado de Node.

Si va al repositorio de recuperación y lee las discusiones, el hecho de que la recuperación se trata de una API moderna con capacidades en lugar de azúcar sintáctico queda muy claro.

@benjamingr Has apoyado tu propio caso aquí. Según su explicación, window.fetch es una API moderna de bajo nivel para navegadores que tiene más funciones que XMLHTTPRequest . Esto es lo mismo para Node.

Por ejemplo, tome la opción redirect: 'follow' en la API window.fetch. En Node.js, necesita https://www.npmjs.com/package/follow-redirects que permite esto.

@Richienb para ser claro: no me opongo a buscar en el núcleo, solo digo que históricamente la búsqueda no se agregó a los navegadores porque era de nivel superior, se agregó porque era de _nivel inferior_.

Los redireccionamientos son diferentes entre navegadores y Node debido al modelo de agente y redirects: follow es en realidad una _API de nivel inferior_ que la que tenía XHR (siempre siga los redireccionamientos, eso no es configurable). El HTTP de Node también es una API de bajo nivel, por lo que, a diferencia de XHR, no siempre sigue los redireccionamientos.


Para ser claros, la búsqueda actualmente solo está bloqueada en el núcleo porque es _mucho trabajo y esfuerzo_ agregarlo bien al núcleo y hay muchos peldaños primero (como averiguar qué hacer con AbortController y las secuencias WHATWG). Fetch no está bloqueado en el núcleo porque no lo queremos en el núcleo.

Lo que creo que nos gustaría evitar es una situación de recuperación similar a Deno que no cumple, aunque creo que trabajar juntos con organismos de estándares puede darnos un buen punto medio donde tenemos un subconjunto de recuperación que es verdaderamente universal y tiene sentido. (Para ser claros, esto no es una falta de respeto a Deno, donde están/estaban haciendo un esfuerzo real para hacer una búsqueda de quejas de especificaciones para JavaScript del lado del servidor y están chocando con un montón de paredes con las especificaciones que lo hacen muy, muy difícil)

Los animo a que se involucren en cualquiera de esos esfuerzos; en su mayoría se están moviendo lentamente debido a la cantidad de esfuerzo que requieren y la prioridad. Este no es uno de los lugares en los que estamos estancados en el desacuerdo.

Actualización rápida: ahora tenemos compatibilidad experimental con EventTarget y AbortController en master. En un futuro no muy lejano, exploraré la compatibilidad con Blob/File API y un poco más de los fundamentos de las transmisiones de WHATWG. No sé si llegaremos a implementar fetch, pero deberíamos poder proporcionar muchos de los componentes necesarios.

deno es increíble, pero está escrito por rust que la sintaxis es muy difícil, oh dios mío. Espero que nodejs admita más y más características de ecmascript o nodejs será heredado y reemplazado por deno. @jasnell, ¿ cuándo lanzar la función EventTarget y AbortController ?

No sé si llegaremos a implementar fetch, pero deberíamos poder proporcionar muchos de los componentes necesarios.

¿Qué hay de explorar una forma de contribuir a la especificación de recuperación y solicitar una API que nos permita devolver tipos personalizados y no usar flujos whatwg (o negociación)?

@anlexN deno y node no están en conflicto ni son enemigos. Node debe agregar funciones cuando sea útil, compasivo y bueno para nuestros usuarios y la salud de la plataforma.

En todo caso, el hecho de que Deno fuera pionero en una plataforma creada con EventTarget nos ayudó a agregar EventTarget, lo mismo para las promesas y AbortController.

No tomemos un ecosistema con más de un proyecto que es una OMI netamente positiva como algo más que eso (una neta positiva).

Creo que la mejor manera de lidiar con las transmisiones es eventualmente (dentro de mucho tiempo) cambiar a las transmisiones whatwg desde las transmisiones de Node por completo, pero creo que, por ahora, implementarlas como un global debería ser un buen paso adelante.

La mayoría de las personas siguen enfocándose en las API y en los Streams. Las API y el código son el menor de los problemas para tener una recuperación compatible con el estándar.

No creo que podamos implementar una recuperación compatible como global, principalmente porque la especificación asume que solo hay un usuario por contexto JS. Node.js como tiempo de ejecución del servidor admite múltiples usuarios simultáneos. Esto se refleja en muchas partes críticas de la especificación, como el modelo de seguridad, el almacenamiento en caché, el manejo de cookies, el manejo de sockets de mantenimiento, el manejo de HTTP/1.1 frente a HTTP/2 y, en el futuro, HTTP/3. Esencialmente, fetch es de _nivel bajo_ para los navegadores pero de _nivel alto_ para Node.js.

Resolver esos problemas es una __cantidad significativa de trabajo__ y hasta ahora nadie ha estado dispuesto a patrocinarlo: mi estimación es que es un esfuerzo de 3 a 6 meses para que un ingeniero competente en estándares haga algo experimental, y probablemente otros 6-12. meses de trabajo estándar para tener una especificación sobre cómo se ve una "búsqueda del lado del servidor".

El problema clave es que node-fetch resuelven el problema realmente bien y no hay _ningún beneficio percibido_ que justifique el esfuerzo de desarrollo.

Ayudando un poco con node-fetch , sé que hay muchos componentes involucrados, por lo que lo más probable es que se quede un poco más antes de que el núcleo del nodo lo obtenga. Darnos acceso a componentes más pequeños para empezar ayudará a largo plazo

Algún tipo de árbol de dependencia del componente más bajo al más alto:

  • Blob+blobAlmacenamiento

    • archivos



      • Formulario de datos



    • Objetivo de evento

    • AbortController

    • Señal de cancelación



      • corrientes de Whatwg



    • Encabezados (piense que esto podría ser algo separado que podría funcionar con otras bibliotecas e incluso con http(s))

Mi objetivo personal realmente no es implementar fetch en el núcleo, sino implementar las partes constituyentes para permitir que la implementación de la zona de usuario sea mejor, particularmente cuando esas partes se pueden usar de manera efectiva para otros usos en el núcleo. EventTarget y AbortController son donde estoy comenzando, pero una vez que avance un poco más en el camino con un par de otros elementos en mi lista de tareas, planeo mirar las API de Blob y File... en gran parte porque creo que Blob y El archivo se puede utilizar para aumentar el rendimiento en otras áreas (API de respondeWithFile). Hay mucho trabajo por hacer en ese sentido.

¿Es posible tomar la implementación de cromo y luego conectarla al nodo?

@ wood1986 no es probable debido a los problemas de almacenamiento en caché y "agencia" descritos anteriormente. La implementación de pila y recuperación HTTP de Chrome contiene una gran cantidad de lógica que Node no puede reutilizar (por seguridad, limitando la concurrencia por host y el almacenamiento en caché) y también está estrechamente acoplada internamente y, a menos que realicen una refactorización significativa, no veo una manera de compartir ese codigo

Creo que sería genial si el proxy definido por el entorno pudiera ser compatible con la futura API central fetch . Sin duda, existe una demanda considerable de esta función y Node parece ser el único "lenguaje" importante del lado del servidor que no cuenta con dicho soporte integrado.

Hola a todos, según los comentarios anteriores, siento que fetch en el núcleo del nodo sigue siendo una melodía del futuro lejano debido a la cantidad de trabajo involucrado y los desafíos técnicos.

Me gustaría proporcionar un punto de datos de alto nivel de mi parte y tal vez una nueva perspectiva (no estoy seguro). No se trata únicamente de fetch sino de redes en general. (Lo siento si encuentra mi comentario fuera de tema y si discusiones como esta ya han ocurrido inevitablemente antes).

En mi opinión, hay dos usos principales de nodejs en la naturaleza:

1) servidores de producción de alto tráfico
2) construir cadenas de herramientas de desarrolladores JS front-end, herramientas de línea de comandos y fragmentos de código

Siento que la mayoría de los colaboradores principales que discuten aquí se enfocan únicamente en el caso de uso 1). (puede ser que esté equivocado)
Personalmente, he estado usando node principalmente para el caso de uso 2) durante una buena década.

Cuando se trata de servidores de producción, los desarrolladores pueden usar el módulo http o bibliotecas probadas en batalla, no hace mucha diferencia porque _tienes mucho código de todos modos, y muchas dependencias de npm también._ También de acuerdo con el sentimiento de "mantener el núcleo pequeño".

Pero cuando se trata de herramientas de línea de comandos, tener una manera fácil de hacer HTTP GET _sin dependencia_ en una línea de código es, en mi opinión, _altamente_ deseable. Veamos qué ofrecen otros lenguajes de programación:

ir: http.Get("https://example.com/")
pitón3: urllib.request.urlopen("https://example.com/").read()
php: file_get_contents("https://example.com/")

No uso ninguno de esos idiomas a diario, y probablemente esas API tengan límites y trampas, pero
probablemente pueda admitir que las API parecen realmente simples y fáciles de recordar.

Mientras que hacer algo similar en el nodo con http / https requiere copiar y pegar un texto estándar considerable y, sinceramente, es bastante frustrante.

En mi opinión, incluso si no es posible implementar en el nodo fetch que cumpla con las especificaciones, o si es un largo camino por recorrer para tenerlo, aún sería deseable algo más (incluso si es muy limitado).

(Habiendo dicho eso, entiendo completamente que no es posible enviar una función y decirle a la gente "no la use en servidores de producción" porque en el momento en que esté allí, la gente _comenzará_ a usarla mal).

Me encantaría algún día poder hacer algo similar al fragmento a continuación con el nodo (funciona con los navegadores) y usarlo en mis scripts desechables rápidos, PoC, alias, etc.

node -p "(await (await fetch('https://api.example.com/stuff')).json()).list.map(o => o.id).join(',')"

sin tener que agregar un asterisco "recuerda instalar npm some-package".

La forma concisa de hacer llamadas HTTP hace que sea más fácil experimentar, compartir código a través de Slack, en piezas de documentación, etc.
En mi opinión, el valor agregado supera la regla de "mantener el núcleo pequeño".

Algunos puntos finales: las características como:

  • Similitud en cuanto a API con fetch ,
  • Campanas y silbatos como aceptar objeto como param, codificarlo como urlen,
  • Soporte para transmisión,

etc. son agradables de tener, pero (en mi opinión) no son necesarios. Un envoltorio de conveniencia realmente simple y limitado de más http(s) realmente sería de gran ayuda.

Soy genéricamente +1 para agregar algo así.

Creo que estamos muy cerca de obtener fetch-without-streams-and-security-rules en términos del código que necesitamos (con AbortController y EventTarget y sin transmisiones).

Estoy a favor de hacer node-fetch-without-streams-or-node-streams para la primera iteración y agregar soporte de flujos más adelante.

Me gustaría que fetch eventualmente fuera "real whatwg fetch" eventualmente y no "algo llamado fetch pero completamente diferente".

Quiero decir que aún podemos decidir hacer http/promises además de o en lugar de fetch y no tener que implementar flujos whatwg, etc. También estoy de acuerdo con https://github.com/ nodejs/node/issues/19393#issuecomentario -647133028

Creo que estamos muy cerca de aterrizar fetch-without-streams-and-security-rules

Estoy a favor de hacer node-fetch-without-streams-or-node-streams para la primera iteración y agregar soporte de flujos más tarde.

Creo que un nivel más bajo de iterador asíncrono o un flujo de nodos sería mejor que nada, incluso si no está en la misma pista que la especificación.
Entonces podrías hacer stream.Readable.from(iterable) o whatwg.ReadableStream.from(iterable) o simplemente hacer:

for await (let chunk of res.body) { ... }

Este código funcionaría para cualquier tipo de cuerpo que sea, ya sea iterable asíncrono, flujo de nodo o flujo whatwg, ya que todo se comporta de la misma manera con respecto a ser iterable asíncrono y producir uint8arrays.

Preferiría un nivel más bajo de un iterable asíncrono más simple si las transmisiones whatwg parecen demasiado lejanas. Entonces aún tendría los beneficios de producir y consumir cuerpos grandes usando fetch.
ofc, una advertencia de la consola podría ser útil para usar iteradores (e informar al usuario que aún no admitimos transmisiones reales) y tal vez iteradores obsoletos más adelante cuando/si whatwg streams se agregan a node. Creo que transformar un iterador en un flujo es muy fácil con solo x.from(iterable)

Pero estoy bien con node-fetch-without-streams-or-node-streams y fetch-without-streams-and-security-rules es una buena primera iteración, tiene que empezar en alguna parte.

Pero también creo que podría ser bueno admitir flujos whatwg y flujos de nodos durante un período de transición para trabajar con ambos y simplemente tratarlos a ambos como un iterador asíncrono, ya que se puede usar de la misma manera cuando se usa un iterador asíncrono + allí. Todavía hay muchas API de nodo integradas que usan flujos de nodo.

Quiero decir que aún podemos decidir hacer http/promises además de o en lugar de buscar y no tener que implementar flujos whatwg, etc. También estoy de acuerdo con #19393 (comentario)

Al igual que esta idea también, sería genial si http tuviera algunos métodos de recuperación agregados como .text() , .json() y .arrayBuffer() para empezar. pero todavía quiero transmisiones whatwg en el nodo también

La primera implementación debe ser estrictamente compatible con las API basadas en promesas existentes, luego, más adelante, podemos ampliar con cosas más avanzadas como iterator/stream (con suerte de una manera estandarizada).

En mi opinión, buscar internamente se puede construir, sin embargo, es mejor para node. Como desarrollador de node.js, no me importa si la búsqueda interna usa flujos, o lo que sea. Tampoco me importa si está construido de manera completamente diferente a window.fetch().

En cambio, lo ÚNICO que me importa, como desarrollador de node.js, es que tiene exactamente el mismo comportamiento de api y api que la api window.fetch().

Ejemplo: Quiero usar fetch y su API prometida, igual que window.fetch() o node-fetch. Pero no me importa cuán internamente se resuelva la promesa, es decir, dentro de una transmisión, un evento, una devolución de llamada o lo que sea.

A veces suena aquí, como que una API de búsqueda en node.js tiene que "funcionar" exactamente de la misma manera que la API de búsqueda original. Pero no creo que esto sea cierto. Debe "hacer" las mismas cosas, "comportarse" de la misma manera y debe "tener" exactamente la misma API, pero de ninguna manera tiene que "funcionar" exactamente de la misma manera.

En mi opinión.

@MBODM

exactamente el mismo comportamiento de api y api

Esta es la razón por la cual implementar fetch en Node.js es un desafío. Hay mucho contexto en este tema en cuanto a por qué.

@bnb tenga en cuenta que mencionan que node-fetch y window.fetch tienen la misma API, lo que confirma la idea de que _no tenemos que cumplir con las especificaciones_.

No quiero agregar más sal a la herida, pero sí, para muchos de nosotros, desde nuestra perspectiva, node-fetch hace el trabajo, puede que no sea perfecto, pero lo hace.

Personalmente, no me importaría si fetch tiene restricciones y sigue las especificaciones del navegador, mientras que el módulo http le permite implementar situaciones más complejas y tener más control sobre la situación de red que puede tener.

En el peor de los casos, nosotros, en nuestra capa de aplicación, tendremos que lidiar con las diferencias entre cada implementación, si queremos tener una sola API que intercambie el cliente HTTP 🤷🏻

Como hacemos hoy con isomorphic-fetch o cualquier otro de esos paquetes, todo lo que pedimos es un poco de apoyo de los principales contribuyentes y hacernos la vida más fácil con abstracciones que definitivamente valen la pena.

Previamente había propuesto incrustar node-fetch en node y exponerlo como http.fetch.

Podría valer la pena explorar esta idea un poco más.

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

stevenvachon picture stevenvachon  ·  3Comentarios

srl295 picture srl295  ·  3Comentarios

Icemic picture Icemic  ·  3Comentarios

danielstaleiny picture danielstaleiny  ·  3Comentarios

jmichae3 picture jmichae3  ·  3Comentarios