Zum Hauptinhalt springen


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

  1. Fordern Sie einen Token an von Ihrer Herkunft.
  2. 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

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
TextDecoderoder 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