簡體   English   中英

將 JSON 數據作為每個塊的 stream 返回到 Angular2 或通過 HTTP2 (HTTPS) 返回 jQuery

[英]Returning JSON data as a stream per chunk to Angular2 or jQuery over HTTP2 (HTTPS)

在我的一個 API 中,我主要在json數組中作為一個整體返回一個結果(假設分頁 50 個結果),如下所示:

[{},{},{},{},{},...]

我想知道是否有更好的方法通過 HTTP2(因為它有許多新的部分流功能)使用 Go 的 HTTP 服務器(在這個項目中使用 Gin 中的 HTTPS)。

也許我可以將每個{}結果分塊並將它們作為段發送到 stream 上? AJAX 在 Angular 或 jQuery 中的調用如何知道傳遞了一個新塊(換行符或某些字符標記?)? 庫中的什么調用實際上可以處理這樣的多重承諾(甚至存在嗎?:P)? 我能否以某種方式從 HTTP2 流功能中受益,以防止打開多個連接?

我的目標是讓結果在出現時很好進入列表。

更新

也許以某種方式使用Keep-Alive header 更容易讓我們保持連接打開一定的秒數,以便能夠 stream 並觸發許多較小的請求/響應?

如我所見, application/x-ndjson可以幫助您。

這是一個使用標准net/http package 的示例。您也可以移植到 GIN。

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "time"
)

// let's generate some fake data
func sampleStream() <-chan []byte {
    out := make(chan []byte, 10)
    go func() {
        for i := 0; i < 10; i++ {
            d := map[string]interface{}{"hello": i}
            buf, _ := json.Marshal(d)
            out <- buf
            time.Sleep(200 * time.Millisecond)
        }
        close(out)
    }()
    return out
}

func streamJSON(w http.ResponseWriter, r *http.Request) {
    flusher, ok := w.(http.Flusher)
    if !ok {
        w.WriteHeader(500)
        w.Write([]byte("Server unsupport flush"))
        return
    }

    // proper handle cors !!!
    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Header().Set("Content-Type", "application/x-ndjson")
    w.Header().Set("Connection", "Keep-Alive")
    w.Header().Set("X-Content-Type-Options", "nosniff")
    for buf := range sampleStream() {
        w.Write(buf)
        w.Write([]byte("\n"))
        flusher.Flush()
    }
}

func main() {
    http.HandleFunc("/", streamJSON)
    s := &http.Server{
        Addr: ":8080",
    }
    fmt.Println("Listen :8080")
    if err := s.ListenAndServe(); err != nil {
        panic(err)
    }
}

和簡單的 JS:

const abortController = new AbortController();

async function main() {
  const res = await fetch("http://localhost:8080", {
    signal: abortController.signal,
  });
  const reader = res.body.getReader();
  const textDecoder = new TextDecoder();
  try {
    while (true) {
      const { done, value } = await reader.read();
      if (done) {
        break;
      }
      const text = textDecoder.decode(value);
      const json = JSON.parse(text);
      console.log(json);
    }
  } finally {
    reader.releaseLock();
  }
}

查找服務器發送的事件。 它本質上是瀏覽器已經內置支持的分塊響應。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM