Vamos começar explicando como os dados são enviados pela web. Não é enviado como um único fluxo contínuo; em vez disso, é dividido em pedaços menores. No lado receptor, o consumidor ou aplicativo é responsável por remontar esses pedaços na ordem e no formato corretos, uma vez que todos os dados tenham sido recebidos. Esse processo acontece automaticamente para imagens, vídeos e outros tipos de dados relativamente grandes.
Então, o que a API Streams oferece é uma maneira de, em vez de esperar que seus dados completos estejam disponíveis
Texto revisado: "O que a API Streams oferece é uma maneira de lidar com os dados conforme eles chegam, em vez de esperar que todo o conjunto de dados esteja disponível. Aqui estão dois benefícios principais:
Vamos começar comparando o método tradicional de recebimento de dados usando a API Fetch com a nova abordagem da API Streams.
fetch("url") .then((response) => { // Note that there is a middle step before we receive the final data // Let's see what we actually receive console.log(response.body); return response.text(); }) .then((data) => { // Perform operations with the data });
Neste exemplo, response.body é um objeto ReadableStream:
ReadableStream { locked: false, state: 'readable', supportsBYOB: true }
Aqui, encontramos o primeiro componente da API Streams: ReadableStream. O construtor ReadableStream cria e retorna um objeto de fluxo legível, o que nos permite lidar com dados de streaming com mais eficiência. Podemos usar esse construtor para gerenciar dados em partes, em vez de esperar que todo o conjunto de dados esteja disponível.
{ arrayBuffer(): Promise; blob(): Promise ; formData(): Promise ; json(): Promise ; text(): Promise ; }
Precisamos implementar uma função que manipule o objeto para acessar os dados conforme eles são enviados em tempo real. Esta função deve:
1 Receba o ReadableStream como uma promessa.
Mergulhando no ReadableStream
interface ReadableStream{ readonly locked: boolean; cancel(reason?: any): Promise ; getReader(options: { mode: "byob" }): ReadableStreamBYOBReader; getReader(): ReadableStreamDefaultReader ; getReader(options?: ReadableStreamGetReaderOptions): ReadableStreamReader ; pipeThrough ( transform: ReadableWritablePair , options?: StreamPipeOptions ): ReadableStream ; pipeTo( destination: WritableStream , options?: StreamPipeOptions ): Promise ; tee(): [ReadableStream , ReadableStream ]; }
interface ReadableStreamDefaultReaderextends ReadableStreamGenericReader { read(): Promise >; releaseLock(): void; }
Para trabalhar com o stream, usamos getReader() que retorna um ReadableStreamDefaultReader.
Aqui está um exemplo em que fazemos uma solicitação à API do Lichess.org para jogos no formato PGN (pense nisso como texto) para um determinado usuário. O resultado final deverá estar em texto.
fetch("https://lichess.org/api/games/user/gg").then((response) => { console.log(response); const readablestream = response.body; console.log(readablestream); const reader = readablestream.getReader(); console.log(reader); });
Saída:
ReadableStream { locked: false, state: 'readable', supportsBYOB: true } ReadableStreamDefaultReader { stream: ReadableStream { locked: true, state: 'readable', supportsBYOB: true }, readRequests: 0, close: Promise {} }
observe que você não pode ter vários leitores ao mesmo tempo, pois getReader() gerará um erro se ReadableStream.locked = true, então se você quiser alterar o leitor, primeiro você deve liberar o bloqueio usando ReadableStreamDefaultReader. releaseLock()
fetch("https://lichess.org/api/games/user/gg").then((response) => { const readablestream = response.body; console.log(readablestream); const reader = readablestream.getReader(); console.log(reader); try { reader.releaseLock(); const reader2 = readablestream.getReader(); // won't throw an error const reader3 = readablestream.getReader(); // will throw an error } catch (e) { console.error(e.message); // Invalid state: ReadableStream is locked } });
agora usamos a função read dentro do leitor que possui duas variáveis
let string = result.push( value.reduce((p, c) => { return p c.fromCharCode(); }, "") ); // or let string = new TextDecoder().decode(value); // both achieve the same thing converting Uint8Array to string
Exemplo de código completo
fetch("https://lichess.org/api/games/user/gg") .then((response) => { return new Promise((resolve, reject) => { const readablestream = response.body; const reader = readablestream.getReader(); let result = []; reader.read().then(function handlechunks({ done, value }) { if (done) { resolve(result); return; } const pgn = new TextDecoder().decode(value); result.push(pgn); reader.read().then(handlechunks); }); }); }) .then((result) => { console.log(result); });
// console.log(value) Uint8Array(551) [ 91, 69, 118, 101, 110, 116, 32, 34, 82, 97, 116, 101, 100, 32, 98, 108, 105, 116, 122, 32, 103, 97, 109, 101, 34, 93, 10, 91, 83, 105, 116, 101, 32, 34, 104, 116, 116, 112, 115, 58, 47, 47, 108, 105, 99, 104, 101, 115, 115, 46, 111, 114, 103, 47, 90, 122, 78, 66, 90, 119, 100, 71, 34, 93, 10, 91, 68, 97, 116, 101, 32, 34, 50, 48, 50, 48, 46, 48, 49, 46, 49, 48, 34, 93, 10, 91, 87, 104, 105, 116, 101, 32, 34, 86, 101, 101, 118, 101, 101, 50, ... 451 more items ] // console.log(new TextDecoder().decode(value)) [Event "Rated blitz game"] [Site "https://lichess.org/ZzNBZwdG"] [Date "2020.01.10"] [White "Veevee222"] [Black "gg"] [Result "0-1"] [UTCDate "2020.01.10"] [UTCTime "20:21:02"] [WhiteElo "1858"] [BlackElo "1863"] [WhiteRatingDiff "-6"] [BlackRatingDiff " 35"] [Variant "Standard"] [TimeControl "180 0"] [ECO "C00"] [Termination "Normal"]
1. e4 e6 2. d4 d6 3. c4 Nf6 4. Nc3 c5 5. f4 cxd4 6. Qxd4 Nc6 7. Qd1 b6 8. g3 Bb7 9. Bg2 Rc8 10. Nf3 Be7 11. O-O O-O 12. b3 Nb4 13. Bb2 a5 14. Re1 Qc7 15. a3 Na6 16. Rc1 Nc5 17. Qd4 Nxb3 18. Qd1 Nxc1 19. e5 0-1
por exemplo link
por exemplo, código completo go
Agora podemos acessar os PGNs dos jogos progressivamente à medida que eles são enviados pela rede. Por exemplo, se estivermos usando os jogos carregados em uma UI de site, o usuário não terá que esperar na frente de uma tela em branco ou de carregamento até que todos os jogos sejam carregados. Em vez disso, os dados podem ser exibidos progressivamente, o que é muito melhor do ponto de vista de UX.
por exemplo, código completo, clique aqui
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3