Contenidos
Aktualisiert
Chrome 85 verfügt über eine experimentelle Implementierung von Anforderungsabläufen. Dies bedeutet, dass Sie eine Anforderung stellen können, bevor der gesamte Text verfügbar ist.
Sie könnten dies verwenden, um:
- Heizen Sie den Server auf. Mit anderen Worten, Sie können die Anforderung starten, sobald sich der Benutzer auf ein Texteingabefeld konzentriert und alle Überschriften entfernt hat. Warten Sie dann, bis der Benutzer auf "Senden" klickt, bevor Sie die eingegebenen Daten senden.
- Senden Sie nach und nach generierte Daten an den Client, z. B. Audio-, Video- oder Eingabedaten.
- Erstellen Sie Web-Sockets über HTTP neu.
Da es sich jedoch um eine Low-Level-Webplattform handelt, beschränken Sie sich nicht darauf mich Ideen. Vielleicht können Sie sich einen viel interessanteren Anwendungsfall für das Anforderungs-Streaming vorstellen.
Testen Sie die Anforderungssequenzen
Aktivieren Sie die Unterstützung während der Herkunftsnachweisphase
Streams für Wiederherstellungsanforderungen sind in einem Ursprungsnachweis verfügbar, der mit Chrome 85 beginnt. Der Ursprungsnachweis wird voraussichtlich in Chrome 87 abgeschlossen sein.
Mit Origin-Tests können Sie neue Funktionen testen und der Community für Webstandards Feedback zu deren Benutzerfreundlichkeit, Praktikabilität und Effektivität geben. Weitere Informationen finden Sie in der Origin-Testhandbuch für Webentwickler. Um sich für diesen oder einen anderen Herkunftsnachweis anzumelden, besuchen Sie die Registrierungsseite.
Registrieren Sie sich für den Herkunftsnachweis
- Fordern Sie einen Token an von Ihrer Herkunft.
- Fügen Sie das Token Ihren Seiten hinzu. Es gibt zwei Möglichkeiten, dies zu tun:
- Füge hinzu ein
Ursprungsversuch
Tag zum Header jeder Seite. Dies könnte beispielsweise folgendermaßen aussehen:
- Wenn Sie Ihren Server konfigurieren können, können Sie das Token auch mit a hinzufügen
Origin-Trial
HTTP-Header. Der resultierende Antwortheader sollte folgendermaßen aussehen:Origin-Trial: TOKEN_GOES_HERE
- Füge hinzu ein
Aktivierung über chrome: // flags
Testen Sie Anforderungs-Streams in Chrome 85, indem Sie ein experimentelles Flag umdrehen:
Enable-Experimental-Web-Plattform-Funktionen
.
Manifestation
Dies zeigt, wie Sie Benutzerdaten an den Server übertragen und Daten senden können, die in Echtzeit verarbeitet werden können.
Ja, okay, nicht das einfallsreichste Beispiel, ich wollte es einfach halten, okay?
Wie funktioniert das überhaupt?
Zuvor auf den aufregenden Abenteuern von Fetch Streams
Antworten Streams sind seit einiger Zeit in allen modernen Browsern verfügbar. Mit ihnen können Sie auf Teile einer Antwort zugreifen, wenn diese vom Server eingehen:
const response = warte auf fetch ( url ) ;
const reader = Antwort . Körper . getReader ( ) ; while ( wahr ) {
const { value , done } = warte auf den Leser . read ( ) ;
wenn ( fertig ) brechen ;
Konsole . log ( 'Received' , Wert ) ;
}}
Konsole . log ( 'Antwort vollständig empfangen' ) ;
Jeder Wert
ist ein Uint8Array
Bytes. Die Anzahl der Arrays und die Größe der Arrays hängen von der Geschwindigkeit des Netzwerks ab. Wenn Sie eine schnelle Verbindung haben, erhalten Sie weniger "Blöcke" größerer Daten. Wenn Sie eine langsame Verbindung haben, erhalten Sie mehr kleinere Blöcke.
Wenn Sie die Bytes in Text konvertieren möchten, können Sie verwenden
TextDecoder
oder der neueste Transformationsstrom, wenn Ihr Zielbrowser unterstützen dies:
const response = warte auf fetch ( url ) ;
const reader = Antwort . Körper
. pipeThrough ( neuer TextDecoderStream ( ) )
. getReader ( ) ;
TextDecoderStream
ist ein Transformationsstrom, der all diese einfängt Uint8Array
Fragmente und verwandelt sie in Strings.
Die Streams sind großartig, da Sie beim Eintreffen auf die Daten reagieren können. Wenn Sie beispielsweise eine Liste mit 100 "Ergebnissen" erhalten, können Sie das erste Ergebnis anzeigen, sobald Sie es erhalten, anstatt auf 100 zu warten.
Wie auch immer, das sind Antwortströme. Das Neue und Aufregende, über das ich sprechen wollte, ist der Anforderungsdatenstrom.
Übermittlungsanforderungsstellen
Anfragen können Körper haben:
warte auf den Abruf ( url , {
Methode : 'POST' ,
body : requestBody ,
} ) ;
Früher war der gesamte Körper einsatzbereit, bevor Sie die Anforderung starten konnten. Jetzt können Sie in Chrome 85 Ihren bereitstellen ReadableStream
von Dateien:
Funktion warten ( Millisekunden ) {
Rückkehr neue Promise ((Entschlossenheit) => setTimeout (resolve, Millisekunden));
}} const stream = neuer ReadableStream ( {
asynchroner Start ( Controller ) {
Await wait (1000);
Controller . Enqueue ( 'This' ) ;
Await wait (1000);
Controller . Enqueue ( 'is' ) ;
Await wait (1000);
Controller . Enqueue ( 'a' ) ;
Await wait (1000);
Controller . Enqueue ( 'langsam' ) ;
Await wait (1000);
Controller . Enqueue ( 'Anfrage.' ) ;
Controller . close ( ) ;
} ,
} ) . pipeThrough ( neuer TextEncoderStream ( ) ) ;
holen ( url , {
Methode : 'POST' ,
Header : { 'Content-Type' : 'text / plain' } ,
Körper : Strom ,
} ) ;
Dadurch wird "Dies ist eine langsame Anforderung" wortweise an den Server gesendet, wobei zwischen den einzelnen Wörtern eine Pause von einer Sekunde eingelegt wird.
Jeder Teil des Textes einer Anfrage muss a sein Uint8Array
von Bytes, also benutze ich
pipeThrough (neuer TextEncoderStream ())
die Konvertierung für mich zu tun.
Aufzeichnbare Streams
Manchmal ist es einfacher, mit Getrieben zu arbeiten, wenn Sie eines haben WritableStream
. Sie können dies tun, indem Sie eine 'Identitäts'-Sequenz verwenden, bei der es sich um ein lesbares / beschreibbares Paar handelt, das alles, was an sein Schreibende übergeben wird, an das Leseende sendet. Sie können eine davon erstellen, indem Sie eine erstellen TransformStream
ohne Argument:
const { lesbar , beschreibbar } = new TransformStream ( ) ; const responsePromise = fetch ( url , {
Methode : 'POST' ,
Körper : lesbar ,
} ) ;
Jetzt ist alles, was Sie an den Schreibstrom senden, Teil der Anfrage. Auf diese Weise können Sie Streams zusammenstellen. Hier ist zum Beispiel ein dummes Beispiel, bei dem Daten von einer URL abgerufen, komprimiert und an eine andere URL gesendet werden:
const response = warte auf den Abruf ( url1) ;
const { lesbar , beschreibbar } = new TransformStream ( ) ;
Antwort . Körper
. pipeThrough ( neuer CompressionStream ( 'gzip' ) )
. pipeTo ( beschreibbar ) ;
warte auf den Abruf ( url2, {
Methode : 'POST' ,
Körper : lesbar ,
} ) ;
Das obige Beispiel verwendet Kompressionsströme um beliebige Daten mit gzip zu komprimieren.
Funktionserkennung
Wenn Sie ein Body-Objekt angeben, das der Browser nicht speziell verarbeitet, wird es aufgerufen toString ()
auf das Objekt und verwenden Sie das Ergebnis als Körper. Wenn der Browser keine Anforderungssequenzen unterstützt, bedeutet dies, dass der Anforderungshauptteil wird
"[Objekt ReadableStream]"
- wahrscheinlich nicht das, was Sie an den Server senden möchten. Um dies zu vermeiden, verwenden Sie die Funktionserkennung:
const unterstütztRequestStreams = ! neue Anfrage ( '' , {
body : neuer ReadableStream ( ) ,
Methode : 'POST' ,
} ) . Überschriften . hat ( 'Inhaltstyp' ) ; if ( unterstütztRequestStreams ) {
} else {
}}
Dies funktioniert, weil der Browser a hinzufügt Inhaltstyp
Header von
text / plain; Zeichensatz = UTF-8
auf die Anfrage, wenn der Text Text ist. Der Browser behandelt den Text nur dann als Text, wenn nein Supportanforderungsflüsse, andernfalls wird kein hinzugefügt Inhaltstyp
Header überhaupt.
Beschränkungen
Stream-Anfragen sind ein neues Kraftpaket für das Web, daher gibt es einige Einschränkungen:
Eingeschränkte Weiterleitungen
Bei einigen Formen der HTTP-Umleitung muss der Browser den Anforderungshauptteil erneut an eine andere URL senden. Um dies zu unterstützen, müsste der Browser den Inhalt des Streams puffern, wodurch der Zeitraum überschrieben wird, sodass dies nicht der Fall ist.
Wenn andererseits die Anforderung einen Übertragungskörper hat und die Antwort eine andere HTTP-Umleitung als 303 ist, wird der Abruf abgelehnt und die Umleitung nein verfolgt werden.
303 Weiterleitungen sind zulässig, da sie die Methode explizit in ändern ERHALTEN
und verwerfen Sie den Anforderungshauptteil.
HTTP / 2 nur standardmäßig
Standardmäßig wird der Abruf abgelehnt, wenn die Verbindung nicht HTTP / 2 ist. Wenn Sie Streaming-Anforderungen über HTTP / 1.1 verwenden möchten, müssen Sie teilnehmen:
warte auf den Abruf ( url , {
Methode : 'POST' ,
Körper : Strom ,
allowHTTP1ForStreamingUpload : true ,
} ) ;
Vorsicht:
allowHTTP1ForStreamingUpload
Es ist kein Standard und wird nur im Rahmen der experimentellen Chrome-Implementierung verwendet.
Gemäß den HTTP / 1.1-Regeln müssen Anforderungs- und Antwortstellen a senden
Inhaltslänge
Header, damit die andere Seite weiß, wie viele Daten empfangen werden, oder das zu verwendende Nachrichtenformat ändern klobige Codierung. Bei der Chunky-Codierung ist der Körper in Teile unterteilt, von denen jeder seine eigene Länge hat.
Chunk-Codierung ist bei HTTP / 1.1 weit verbreitet Antworten, aber sehr selten, wenn es darum geht Anfragen. Aus diesem Grund ist Chrome ein wenig besorgt über die Kompatibilität, daher ist es vorerst aktiviert.
Dies ist kein Problem für HTTP / 2, da HTTP / 2-Daten immer "Chunked" sind, obwohl sie Chunks aufrufen
Frames. Die Chunky-Codierung wurde erst mit HTTP / 1.1 eingeführt, sodass Anforderungen mit Streaming-Körpern bei HTTP / 1-Verbindungen immer fehlschlagen.
Abhängig davon, wie dieser Test abläuft, beschränkt die Spezifikation die Streaming-Antworten auf HTTP / 2 oder lässt sie immer sowohl für HTTP / 1.1 als auch für HTTP / 2 zu.
Keine Duplexkommunikation
Eine wenig bekannte Funktion von HTTP (ob dies ein Standardverhalten ist, hängt jedoch davon ab, wen Sie fragen) ist, dass Sie die Antwort empfangen können, während Sie die Anfrage noch senden. Es ist jedoch so wenig bekannt, dass es von Servern und Browsern nicht gut unterstützt wird.
In der aktuellen Chrome-Implementierung erhalten Sie die Antwort erst, wenn der Text vollständig übermittelt wurde. Im folgenden Beispiel responsePromise
Es wird erst aufgelöst, wenn die lesbare Übertragung geschlossen wurde. Alles, was der Server vor diesem Punkt sendet, wird gepuffert.
const responsePromise = fetch ( url , {
Methode : 'POST' ,
body : readableStream ,
} ) ;
Die zweitbeste Option für die Duplexkommunikation besteht darin, nach einer Übertragungsanforderung zu suchen und dann erneut zu suchen, um die Übertragungsantwort zu empfangen. Der Server benötigt eine Möglichkeit, diese beiden Anforderungen zuzuordnen, z. B. eine ID in der URL. So funktioniert die Demo.
Potenzielle Probleme
Ja, also ... dies ist eine neue Funktion, die im Internet heutzutage nicht weit verbreitet ist. Hier sind einige Punkte zu beachten:
Inkompatibilität auf der Serverseite
Einige Anwendungsserver unterstützen keine Streaming-Anforderungen und warten stattdessen, bis die vollständige Anforderung eingegangen ist, bevor Sie etwas sehen können, was den Punkt vereitelt. Verwenden Sie stattdessen einen Anwendungsserver, der Streaming unterstützt, z
NodeJS.
Aber du bist noch nicht aus dem Wald! Der Anwendungsserver befindet sich wie NodeJS normalerweise hinter einem anderen Server, der häufig als "Front-End-Server" bezeichnet wird und sich möglicherweise hinter einem CDN befindet. Wenn einer von ihnen beschließt, die Anforderung zu puffern, bevor sie an den nächsten Server in der Kette gesendet wird, verliert er den Vorteil der Übertragung von Anforderungen.
Wenn Sie HTTP / 1.1 verwenden, ist einer der Server möglicherweise nicht für die Chunk-Codierung bereit und schlägt möglicherweise mit einem Fehler fehl. Aber hey, Sie können das zumindest versuchen und bei Bedarf versuchen, die Server zu wechseln.
... langes Seufzen ...
Inkompatibilität außerhalb Ihrer Kontrolle
Wenn Sie HTTPS verwenden, müssen Sie sich keine Gedanken über Proxys zwischen Ihnen und dem Benutzer machen, aber der Benutzer führt möglicherweise einen Proxy auf Ihrem Computer aus. Einige Internet-Schutzsoftware ermöglicht dies, um alles zu überwachen, was zwischen dem Browser und dem Netzwerk geschieht.
Es kann Fälle geben, in denen die Pufferanforderungskörper dieser Software oder im Fall von HTTP / 1.1 keine klobige Codierung erwarten und diese auf interessante Weise unterbrochen wird.
Derzeit ist unklar, wie oft, wenn überhaupt, dies passieren wird.
Wenn Sie sich davor schützen möchten, können Sie einen 'Feature-Test' ähnlich der obigen Demo erstellen, bei dem Sie versuchen, einige Daten zu streamen, ohne den Stream zu schließen. Wenn der Server die Daten empfängt, kann er über eine andere Suche antworten. Sobald dies geschieht, wissen Sie, dass der Client End-to-End-Streaming-Anforderungen unterstützt.
Kommentare willkommen
Community-Feedback ist für das Entwerfen neuer APIs von entscheidender Bedeutung. Probieren Sie es aus und teilen Sie uns Ihre Meinung mit! Wenn Sie Fehler finden, bitte Melde sie, aber wenn Sie allgemeine Kommentare haben, senden Sie diese bitte an blink-network-dev Google Group.
Foto von Laura Lefurgey-Smith
im
Unsplash