フロントエンドは ReadableStream.getReader を使用してストリーミング レンダリングを処理します


序文

要件: インターフェイスによって返される記事をリクエストに従ってセグメントごとにレンダリングします。同時に、[生成の停止] ボタンをクリックしてリクエストを停止できます。
経験: 純粋な CSS、vue-typed-js プラグイン、および ReadableStream を使用します。最初の 2 つは完璧ではありませんが、トラブルシューティングと問題を段階的に解決するこの方法の方が重要だと私は考えています。効果があるかどうかを緊急に判断する必要がある場合は、直接 3 番目のステップに進むこともできます。
インターフェースによって返されるデータ: 由于是一段一段渲染,所以是数组套对象,如下、完全な文は「私は情熱を持ってそれを待ち望んでいました、そして数え切れないほどの失望と挫折を経験しました、しかし私はついにここに来ました。」

[
    {
    
    
        "header":{
    
    
            "code":"200"
        },
        "chunk":"我"
    },
    {
    
    
        "header":{
    
    
            "code":"200"
        },
        "chunk":"曾满怀激情地"
    },
    {
    
    
        "header":{
    
    
            "code":"200"
        },
        "chunk":"憧憬过,也"
    },
    {
    
    
        "header":{
    
    
            "code":"200"
        },
        "chunk":"曾经历了无数次失望"
    },
    {
    
    
        "header":{
    
    
            "code":"200"
        },
        "chunk":"和沮丧,但最终还是"
    },
    {
    
    
        "header":{
    
    
            "code":"200"
        },
        "chunk":"来到了这里。"
    }
]

1.純粋なCSS

内容が膨大であるため、ここではアイデアについてのみ説明し、具体的な内容には原文へのリンクが表示されます。
すべてのコンテンツを p タグで囲みます。デフォルトでは非表示になっています。次にアニメーションを追加し、最初の 0.5 秒表示、2 番目の 1 秒表示、3 番目の 1.5 秒表示...というようにしていきます。
欠点: n p タグに手動でスタイルを追加する必要があり、コンテンツが固定されている場合にのみ、返されたデータが異なる場合は使用できません。もちろんブログのタイトルもわかりやすく書かれており、本文を一行ずつ表示したり表示することも可能です。

参考記事:
cssアニメーションでテキストを1行ずつ表示: https: //www.5axxw.com/questions/simple/dkog6u
cssアニメーションでテキストを1行ずつ徐々に表示:https: //www.5axxw.com/questions/simple /aawr87
https://www.5axxw.com/questions/simple/vy1p34: https://www.5axxw.com/questions/simple/vy1p34

2 つ、vue-typed-js プラグイン

公式サイトアドレス: https: //github.com/Orlandster/vue-typed-js

1.インストール

npm install --save vue-typed-js

2. 登録する

import Vue from 'vue'
import VueTypedJs from 'vue-typed-js'
 
Vue.use(VueTypedJs)

3.使用する

<vue-typed-js
   :startDelay="1000"
   :cursorChar="'|'"
   :strings="[
     '<span>我</span>',
     '<span>曾满怀激情地</span>',
     '<span>憧憬过,也曾</span>',
     '<span>经历了无数次失望和沮丧,</span>',
     '<span>但最终还是</span>',
     '<span>来到了这里。</span>',
   ]"
   :contentType="'html'"
 >
 </vue-typed-js>

フィールドの詳細:
startDelay 入力遅延時間、単位はミリ秒
CursorChar カーソルの外観を設定します 文字列
レンダリングされるデータを含む
配列 contentType 入力テキストまたは HTML です

要約する

落とし穴はなく、インストールして登録し、直接使用するだけです。しかし、解決できない重大な問題が 1 つあります。strings这个渲染的数组,如果你在vue中watch监听这个数据,每次改变的话,你会发现有旧值和新值,但如果是接口返回的数据,就只会返回数组的第一个对象的值,后面的不会返回拼接数据了,也就是strings在vue-typed-js组件中只会触发一次,

3、ReadableStream

ReadableStream MDN 公式 Web サイトの紹介: https://developer.mozilla.org/zh-CN/docs/Web/API/ReadableStream

1. ReadableStream とは何ですか?

Stream API の ReadableStream インターフェイスは、バイト データの読み取り可能なストリームを表します。Fetch API は、Response 属性本体 (en-US) を通じて特定の ReadableStream オブジェクトを提供します。

2. ReadableStream は何をしますか?

私の理解:インターフェイスの内容をbase64バイトに返し、getReader()を通じてリーダーを作成し、ストリームをロックすることです。現在のリーダーがストリームを解放した後でのみ、他のリーダーがストリームを使用できるようになります。cancel() メソッドは、ストリームがキャンセルされたときに実行される Promise を返します。cancel は、ストリームからのデータが不要になったときに (キューに入れられたデータ ブロックがまだある場合でも) ストリームを完全に終了するために使用されます。このデータは cancel が呼び出された後に失われ、ストリームを読み取ることができなくなります。

3.ReadableStreamの使い方

(1) クロスドメインGoogleブラウザの設定により以下のコードを開くことができます

クロスドメインの Google ブラウザを設定していない場合は、私のブログ [Google (Chrome) ブラウザのクロスドメイン設定] を参照してクロスドメイン ブラウザを作成してください: https://blog.csdn.net/weixin_44784401 /article /詳細/131111077

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <script>
  fetch("https://www.example.org")
  .then((response) => response.body)
  .then((rb) => {
      
      
    const reader = rb.getReader();
    return new ReadableStream({
      
      
      start(controller) {
      
      
        function push() {
      
      
          reader.read().then(({
       
        done, value }) => {
      
      
            if (done) {
      
      
              console.log("done111", done);
              controller.close();
              return;
            }
            controller.enqueue(value);
            console.log("done222", done, value);
            push();
          });
        }
        push();
      },
    });
  })
  
  </script>
</body>
</html>

(2) 効果は
ここに画像の説明を挿入
上図で確認できます: Reader.read().then(({ned, value }) の値は、ReadableStream で読み取れるバイトデータストリームを示します (3) ストリームレンダリングデータと実際のデータを組み合わせた
もの状況 疑似コード、私のものは vue2 プロジェクトです

// 注意:以下代码是伪代码,需要你结合自身需求去修改
let _this = this; // 存储this
  let data = '';
  fetch("https://www.example.org", {
    
    
    method: 'POST',
    body: JSON.stringify(data)
  })
  .then((response) => {
    
    
      const reader = response.body.getReader(); // 创建一个读取器并将流锁定于其上。一旦流被锁定,其他读取器将不能读取它,直到它被释放
      const decoder = new TextDecoder(); // TextDecoder 接口表示一个文本解码器,一个解码器只支持一种特定文本编码,例如 UTF-8、ISO-8859-2、KOI8-R、GBK,等等。解码器将字节流作为输入,并提供码位流作为输出。
      console.log('000', response.body, decoder);
      // 按顺序读取每个分块,并传递给 UI,当整个流被读取完毕后,从递归方法中退出,并在 UI 的另一部分输出整个流。
      function read() {
    
    
        // read() 返回了一个 promise 
        // done  - 当 stream 传完所有数据时则变成 true
        // value - 数据片段。当 done 为 true 时始终为 undefined
        return reader.read().then(({
     
      done, value }) => {
    
    
          if (done) {
    
    
            return;
          }
          let chunkData = ""; // 设置一个存储当前数组对象中数据的字符串
          let chunkJson = JSON.parse(decoder.decode(value)); // decoder.decode(编码)返回一个字符串,其中包含使用特定 TextDecoder 对象的方法解码的文本。(就是将原本变成字节流后把它变成文本)
          // 如果code不是200,说明请求失败,后面不执行
          if (chunkJson.header.code != "200") {
    
    
            return;
          }
          chunkData = JSON.parse(decoder.decode(value)).chunk;
          _this.render.contentText += chunkData; // 请求成功拼接字符串
          // reader.cancel()是reader停止请求的方法,停止请求后就不请求了(有一个停止生成的按钮,点击后就停止请求)
          // render.loading 是判断是否正在请求的loading,以此来判断是否继续递归请求后面的数据
          return _this.render.loading ? read() : reader.cancel();
        });
      }
      return read();
    })

ReadableStream 参照リンク
(1) MDN ReadableStream: https://developer.mozilla.org/zh-CN/docs/Web/API/ReadableStream
(2) MDN ReadableStream getReader() メソッド: https://developer.mozilla.org/ zh-CN/docs/Web/API/ReadableStream/getReader
(3) MDN ReadableStream cancel() メソッド: https://developer.mozilla.org/zh-CN/docs/Web/API/ReadableStream/cancel
(4) MDN TextDecoder: https://developer.mozilla.org/zh-CN/docs/Web/API/TextDecoder

おすすめ

転載: blog.csdn.net/weixin_44784401/article/details/132206265