0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

javascript調査

Posted at

結論?
少なくともHTTPのレイヤでtransfer-encoding:chunkedやHTTP2のフレーム分割を使用することができる
ある程度ならその単位に分割したデータがfetchに取得させることができる
実際にはそのサイズはTCPレイヤとかの制限も入るはずだが確証はない

HTTP1.1 リクエスト→レスポンスは順番に処理されるの関係chunkedを使用することでHTTPのレイヤで分割してデータを送ることができる

HTTP2 リクエスト右レスポンスを多重に処理することができる
そのためHTTPレベルで分割されたパケット事にヘッダが生成される

HTTPヘッダの種類
https://developer.mozilla.org/ja/docs/Web/HTTP/Reference/Headers

fetch APIで読み取れるヘッダがどのヘッダか

定義上はレスポンスもリクエストも同じインターフェース
https://developer.mozilla.org/ja/docs/Web/API/Headers

そもそもストリームとは?

HTTP1.1で1つのリクエストに1つのレスポンスを送受信する

HTTP2では複数のリクエストを並列に処理できるようになっている
→フレームヘッダが必要になっている

→レスポンスを小分けにする(チャンクにする)方法はHTML1.1でも存在する

async function fetchAndMeasureJsonSize(url) {
  let totalBytes = 0;
  let startTime = performance.now(); // 処理開始時刻

  try {
    const response = await fetch(url);

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const reader = response.body.getReader();
    let done, value;

    console.log(`--- Streaming data from: ${url} ---`);

    while (true) {
      ({ done, value } = await reader.read());

      if (done) {
        break; // 全てのデータが読み込まれた
      }

      // valueはUint8Arrayです
      totalBytes += value.byteLength;
      console.log(`Received chunk of ${value.byteLength} bytes. Total: ${totalBytes} bytes.`);
    }

    let endTime = performance.now(); // 処理終了時刻
    let duration = (endTime - startTime) / 1000; // 秒に変換

    console.log(`--- Download complete! ---`);
    console.log(`Total downloaded size: ${totalBytes} bytes`);
    console.log(`Time taken: ${duration.toFixed(2)} seconds`);

    // 必要であれば、完全に読み込んだデータをJSONとしてパースすることも可能ですが、
    // ここではストリームでのサイズ測定が主目的のため割愛します。
    // 例: const text = new TextDecoder().decode(buffer); // bufferは全データを結合したもの
    //     const json = JSON.parse(text);

  } catch (error) {
    console.error('Fetch error:', error);
  }
}
app.get('/chunked-text', (req, res) => {
  // ヘッダーの設定 (Content-Type は必要、Transfer-Encoding: chunked はExpress/Node.jsが自動で追加)
  res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });

  let count = 0;
  const intervalId = setInterval(() => {
    count++;
    //const dataChunk = `データチャンク #${count} - ${new Date().toLocaleTimeString()}\n`;
    const dataChunk = "x".repeat(1024 * 1024); // 1MBのデータチャンクを生成
    console.log(`Sending chunk: ${new Date().toLocaleTimeString()}`);

    // データチャンクを書き込む
    res.write(dataChunk);

    if (count >= 5) {
      clearInterval(intervalId);
      // 全てのデータ送信が完了したら res.end() を呼び出す
      res.end('全てのデータ送信が完了しました。\n');
      console.log('Response ended.');
    }
  }, 1000); // 1秒ごとにチャンクを送信
});
0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?