国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

SSE實(shí)現(xiàn)消息實(shí)時(shí)推送,前端漸進(jìn)式學(xué)習(xí)、實(shí)踐,真香

這篇具有很好參考價(jià)值的文章主要介紹了SSE實(shí)現(xiàn)消息實(shí)時(shí)推送,前端漸進(jìn)式學(xué)習(xí)、實(shí)踐,真香。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

一、SSE概念

SSE(Server Sent Event),直譯為服務(wù)器發(fā)送事件,顧名思義,也就是客戶端可以獲取到服務(wù)器發(fā)送的事件。我們常見的 http 交互方式是客戶端發(fā)起請(qǐng)求,服務(wù)端響應(yīng),然后一次請(qǐng)求完畢;但是在 sse 的場(chǎng)景下,客戶端發(fā)起請(qǐng)求,連接一直保持,服務(wù)端有數(shù)據(jù)就可以返回?cái)?shù)據(jù)給客戶端,這個(gè)返回可以是多次間隔的方式

二、SSE應(yīng)用場(chǎng)景

在web端消息推送功能中,由于傳統(tǒng)的HTTP協(xié)議是由客戶端主動(dòng)發(fā)起請(qǐng)求,服務(wù)端才會(huì)響應(yīng)?;镜腶jax輪詢技術(shù)便是如此。而在SSE中,瀏覽發(fā)送一個(gè)請(qǐng)求給服務(wù)端,通過(guò)響應(yīng)頭中的Content-Type:text/event-stream等向客戶端聲名這是一個(gè)長(zhǎng)連接,發(fā)送的是流數(shù)據(jù),這樣客戶端就不會(huì)關(guān)閉連接,一直等待服務(wù)端發(fā)送數(shù)據(jù)。

如果服務(wù)器返回的數(shù)據(jù)中包含了事件標(biāo)識(shí)符,瀏覽器會(huì)記錄最后一次接收的事件的標(biāo)識(shí)符。如果與服務(wù)器的連接中斷,當(dāng)瀏覽器再次進(jìn)行連接時(shí),會(huì)通過(guò)頭來(lái)聲明最后一次接收的事件的標(biāo)識(shí)符。服務(wù)器端可以通過(guò)瀏覽器發(fā)送的事件標(biāo)識(shí)符來(lái)確定從哪個(gè)事件來(lái)繼續(xù)連接

三、前端使用方法、問(wèn)題

1、get方式

使用eventsource完成get請(qǐng)求

缺點(diǎn):客戶端無(wú)法通過(guò)一個(gè)get請(qǐng)求完成數(shù)據(jù)傳遞

參考文檔:

EventSource - Web API 接口參考 | MDN

實(shí)現(xiàn)流程:

  1. 后端提供了兩個(gè)接口,一個(gè)是:post,用以完成前端信息的傳遞,我這邊是做大語(yǔ)言模型的,所以包括了模型必要參數(shù)、問(wèn)題等;二、get接口,完成流式輸出的接口,配置相應(yīng)的具名事件、請(qǐng)求頭等
  2. 前端通過(guò)調(diào)用post接口拿到本次會(huì)話id,將id攜帶在get請(qǐng)求里,完成信息傳遞
  3. 前端處理SSE流式返回

代碼實(shí)現(xiàn):

const eventSourceRef = useRef<any>(null)
const contact = async (messageData: any) => {
  eventSourceRef.current = new EventSource(
    `${API_BASE}/v1/model/stream?id=${id}`,
  )
  if (!eventSourceRef.current) return
  // 監(jiān)聽 SSE 事件,因?yàn)楹蠖硕x了具名事件,所以這兒要用addEventListener監(jiān)聽,而不是onmessage
  eventSourceRef.current.addEventListener('add', function (e: any) {
	// 處理數(shù)據(jù)展示
  })
  eventSourceRef.current.addEventListener('finish', function (e: any) {
   // 結(jié)束標(biāo)識(shí)finish
    eventSourceRef.current.close() // 關(guān)閉連接
  })
  eventSourceRef.current.addEventListener('error', function (e: any) {
    if (e.status === 401) {
      // 用戶登錄狀態(tài)失效處理
    }
    // error報(bào)錯(cuò)處理
    console.log('Error occurred:', e)
    // 關(guān)閉連接
    eventSourceRef.current.close()
  })
}

2、post方式

使用fetch-event-source完成連接,僅需一個(gè)接口,支持添加請(qǐng)求頭

缺點(diǎn):在瀏覽器返回的text/eventstream里看不到具體返回,無(wú)法進(jìn)行預(yù)覽

參考文檔:

@microsoft/fetch-event-source

實(shí)現(xiàn)流程:

  1. 后端提供一個(gè)接口,支持前端傳參、流式返回
  2. 前端通過(guò)fetch-event-source,完成傳參、請(qǐng)求頭添加等
  3. 處理返回?cái)?shù)據(jù)

具體實(shí)現(xiàn):

  const eventSourceRef = useRef<any>(null)
  const [abortController, setAbortController] = useState(new AbortController())
  // 通信事件
  const contact = async (messageData: any) => {
    messageData = { ...messageData, do_stream: modelArg.do_stream } // 請(qǐng)求參數(shù)
    receivedDataRef.current = ''
    const token: string = getLocal('AUTHCODE') || '' 
    fetchEventSource(`${MAAS_API_BASE}/v1/model_api/invoke`, {
      method: 'POST',
      // 添加請(qǐng)求頭
      headers: {
        Authorization: token,
        'Content-Type': 'application/json',
      }, 
       // 傳參必須保證是json
      body: JSON.stringify(messageData),
      // abortController.signal 提供了一個(gè)信號(hào)對(duì)象給 fetchEventSource 函數(shù)。
      // 如果在任何時(shí)候你想取消正在進(jìn)行的 fetch 操作,你可以調(diào)用 
      // abortController.abort()。這會(huì)發(fā)出關(guān)聯(lián)任務(wù)的信號(hào),你可以使用 
      // AbortController 的信號(hào)來(lái)檢查異步操作是否已被取消。
      signal: abortController.signal, 
      openWhenHidden: true, // 切換標(biāo)簽頁(yè)時(shí)連接不關(guān)閉
      async onopen(resp) {
        // 處理登錄失效
        if (resp.status === 401) {
          message.warning('登錄過(guò)期')
          return
        }
      },
      onmessage(msg: any) {
        const eventType = msg.event // 監(jiān)聽event的具名事件
        switch (eventType) {
          case 'add':
            // 流式輸出事件,add每次會(huì)返回具體字符,前端負(fù)責(zé)拼接展示
            break
          case 'finish':
            setStatu('finish') // 結(jié)束標(biāo)識(shí)
            break
          case 'error':
            if (msg.status === 401) {
               message.warning('登錄過(guò)期')
            }
            console.log('Error occurred:', e)
            break
        }
      },
      onerror(err) {
        throw err // 連接遇到http錯(cuò)誤時(shí),如跨域等,必須要throw才能停止,不然會(huì)一直重連
      },
      onclose() {},
    })
  }

  // 終止連接方法,比如在切換模型時(shí),你可能有必要終止上一次連接來(lái)避免問(wèn)答串聯(lián)
  const closeSSE = () => {
    abortController.abort()
    setAbortController(new AbortController())
  }

3、一種接口同時(shí)兼容流式/非流式

同上post方法

    fetchEventSource(sseUrl, {
      method: 'POST',
      headers,
      signal: abortController.signal,
      body: JSON.stringify(customInferData),
      openWhenHidden: true,
    /**
    *在onopen階段處理
    第一步:判斷resp.headers.get('content-type'),如果不包含text/event-stream,
    則代表非流式
    第二步:需要在onopen階段處理非流式返回,即json返回,讀取json返回并渲染,注意異常也要處理
    第三步:
     */
      async onopen(resp) {
        const contentype = resp.headers.get('content-type') || ''
        console.log('contentype =>', contentype)
        console.log('resp.ok =>', resp.ok)
        if (resp.ok && !contentype.includes('text/event-stream')) {
          // 讀取json數(shù)據(jù)
          const responseData = await resp.json()
          if (responseData.code !== 0) {
             // 報(bào)錯(cuò)處理+關(guān)閉連接
          } else {
            //處理數(shù)據(jù)渲染+關(guān)閉連接
            
            stopSession()
          }
        } else if (resp.status === 401) {
          message.warning('登錄過(guò)期')
          // 報(bào)錯(cuò)處理+關(guān)閉連接
          stopSession()
        
        }
      },
      onmessage(msg: any) {
        const eventType = msg.event
        const messages: any = cloneDeep(chatState.sessionMessages)
        let lastMessage: any = messages[messages.length - 1] || {}

        switch (eventType) {
          case 'add':
            lastMessage = {
              ...lastMessage,
              text: `${lastMessage.text}${msg.data || ' '}`,
              loading: false,
            }
            messages.splice(messages.length - 1, 1, lastMessage)
            chatAction.updateSessionMessages(messages)
            break
          case 'finish':
            console.log('finish lastMessage =>', lastMessage)
            chatAction.updateSessionStatu(SessionStatuTypes.ready)
            chatAction.updateContext(msg.data)
            break
          case 'info':
            {
              const messages: any = cloneDeep(chatState.sessionMessages)
              let lastMessage: any = messages[messages.length - 1] || {}
              lastMessage = {
                referenceDocs: JSON.parse(msg.data).reference_by_docs,
                ...lastMessage,
              }
              messages.splice(messages.length - 1, 1, lastMessage)
              chatAction.updateSessionMessages(messages)
            }
            break
          case 'error':
            if (msg.status === 401) {
              chatAction.updateSessionStatu(SessionStatuTypes.ready)
            } else {
              errorItemFn(msg?.msg || msg?.data || '抱歉,暫無(wú)法回答問(wèn)題')
            }
            break
        }
      },
      onerror(err: any) {
        errorItemFn(err?.msg || '抱歉,暫無(wú)法回答該問(wèn)題')
        console.log('eventSource error: ', `${err}`)
        throw err  // 連接遇到http錯(cuò)誤時(shí),如跨域等,必須要throw才能停止,不然會(huì)一直重連
      },
      onclose() {
        console.log('eventSource close')
      },
    })

  // 終止會(huì)話
  const stopSession = () => {
    abortController.abort()
    setAbortController(new AbortController())
  }

四、常見問(wèn)題匯總

1、無(wú)法添加請(qǐng)求頭

應(yīng)用fetch-event-source解決

2、一個(gè)方法需要同時(shí)兼容流式和非流式

應(yīng)用fetch-event-source在onopen階段處理非流式輸出,如報(bào)錯(cuò)、接口json返回等

3、遇到跨域時(shí)候,請(qǐng)求一直連接

應(yīng)用fetch-event-source在監(jiān)聽具名事件時(shí),如error,將錯(cuò)誤throw err,否則無(wú)法中斷連接文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-832115.html

4、fetch方法如何終止

  const stopSession = () => {
    abortController.abort()
    setAbortController(new AbortController())
  }

到了這里,關(guān)于SSE實(shí)現(xiàn)消息實(shí)時(shí)推送,前端漸進(jìn)式學(xué)習(xí)、實(shí)踐,真香的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Redis-漸進(jìn)式遍歷scan的使用

    Redis-漸進(jìn)式遍歷scan的使用

    目錄 1、為什么使用漸進(jìn)式遍歷? 2、scan的使用 3、漸進(jìn)式遍歷的缺點(diǎn) 4、補(bǔ)充知識(shí)點(diǎn):redis中也區(qū)分database? ? ? ? ? 前面的博客中,我們有提到使用keys *來(lái)獲取所有的key,但這種辦法,當(dāng)Redis中存儲(chǔ)的有很多key時(shí),實(shí)行此命令所耗費(fèi)的時(shí)長(zhǎng)就會(huì)很長(zhǎng),不符合使用規(guī)范,redis一

    2024年02月07日
    瀏覽(27)
  • 寫點(diǎn)東西《漸進(jìn)式網(wǎng)絡(luò)應(yīng)用入門》

    PWA 是一種漸進(jìn)式網(wǎng)絡(luò)應(yīng)用程序,它結(jié)合了應(yīng)用程序的功能和網(wǎng)絡(luò)技術(shù)。 您可以說(shuō)它們是使用網(wǎng)絡(luò)技術(shù)構(gòu)建的應(yīng)用程序,但感覺和功能都像原生應(yīng)用程序。 網(wǎng)絡(luò)應(yīng)用程序似乎變得有限,因?yàn)榇蠖鄶?shù)人更喜歡構(gòu)建移動(dòng)應(yīng)用程序,以便用戶可以將它們保存在手機(jī)上,而不是構(gòu)建網(wǎng)

    2024年01月19日
    瀏覽(26)
  • Vue3 Flask 漸進(jìn)式入門筆記

    以下均在Windows 10環(huán)境下實(shí)現(xiàn)。 安裝node.js的過(guò)程略過(guò)。 1、在cmd命令行中執(zhí)行以下命令: 2、查看vue版本 注意,如果電腦中以前有vue2版本,則需要卸載后重啟電腦再重新安裝,否則有可能安裝失敗。 1、執(zhí)行以下命令以創(chuàng)建項(xiàng)目 第一步需要填寫項(xiàng)目名稱;后面的除router建議選

    2024年02月09日
    瀏覽(18)
  • Unity教程||Unity 漸進(jìn)式光照貼圖烘焙詳解

    隨著各大計(jì)算平臺(tái)的算力穩(wěn)步增長(zhǎng),特別是GPU技術(shù)的不斷進(jìn)化,原先可望而不可及的技術(shù)比如實(shí)時(shí)光線追蹤技術(shù)開始逐步走入玩家的視野。一些先鋒廠商甚至已經(jīng)超出Demo的范疇,開始正式推出支持實(shí)時(shí)光追的游戲。 不過(guò)目前的實(shí)時(shí)光追技術(shù)還只能在配備了最新Nvidia RTX 20系列

    2024年02月08日
    瀏覽(43)
  • 【GitOps系列】如何實(shí)施自動(dòng)化漸進(jìn)式交付?

    【GitOps系列】如何實(shí)施自動(dòng)化漸進(jìn)式交付?

    前言 在實(shí)施金絲雀發(fā)布的過(guò)程中,我們通過(guò) Argo Rollout 的金絲雀策略將發(fā)布過(guò)程分成了 3 個(gè)階段,每個(gè)階段金絲雀的流量比例都不同,經(jīng)過(guò)一段時(shí)間之后,金絲雀環(huán)境變成了新的生產(chǎn)環(huán)境。實(shí)際上,這也是一種漸進(jìn)式的交付方式,它通過(guò)延長(zhǎng)發(fā)布時(shí)間來(lái)保護(hù)生產(chǎn)環(huán)境,降低了

    2024年02月14日
    瀏覽(27)
  • 漸進(jìn)式編程之旅:探尋PHP函數(shù)的奇妙世界

    漸進(jìn)式編程之旅:探尋PHP函數(shù)的奇妙世界

    目錄 前言 一、函數(shù)的定義和調(diào)用 1.1?初識(shí)函數(shù) 1.1.1?函數(shù)分類 1.1.2 自定義函數(shù) 1.1.3?return 1.2 參數(shù)設(shè)置 1.2.1 無(wú)參函數(shù) 1.2.2?按值傳遞參數(shù) 1.2.3?引用傳參 1.2.4?設(shè)置參數(shù)默認(rèn)值 1.2.5?指定參數(shù)類型(弱) 1.3 變量的作用域 1.3.1 變量分類 1.3.2?全局變量的使用 1.3.3?global關(guān)鍵

    2024年02月08日
    瀏覽(21)
  • 漸進(jìn)式web全棧:blazor web app

    漸進(jìn)式web全棧:blazor web app

    本文要說(shuō)的這種開發(fā)模式,這種模式并不是只有blazor支持,js中有一樣的方案next.js nuxt.js;blazor還有很多其它內(nèi)容,本文近關(guān)注漸進(jìn)式開發(fā)模式。 是的,前后端是主流,不過(guò)以下情況也許前后端分離并不是最好的選擇: 小公司,人員不多,利潤(rùn)不高,創(chuàng)業(yè)階段能省則省 個(gè)人

    2024年02月05日
    瀏覽(17)
  • 2023-06-17:說(shuō)一說(shuō)redis中漸進(jìn)式rehash?

    2023-06-17:說(shuō)一說(shuō)redis中漸進(jìn)式rehash?

    2023-06-17:說(shuō)一說(shuō)redis中漸進(jìn)式rehash? 答案2023-06-17: 在Redis中,如果哈希表的數(shù)組一直保持不變,就會(huì)增加哈希沖突的可能性,從而降低檢索效率。為了解決這個(gè)問(wèn)題,Redis會(huì)對(duì)數(shù)組進(jìn)行擴(kuò)容,通常是將數(shù)組大小擴(kuò)大為原來(lái)的兩倍。然而,這個(gè)擴(kuò)容過(guò)程會(huì)引起元素在哈希桶中的

    2024年02月09日
    瀏覽(27)
  • Vue.js:構(gòu)建用戶界面的漸進(jìn)式框架

    Vue.js是一種流行的JavaScript前端框架,用于構(gòu)建用戶界面。本文將介紹Vue.js的基本概念、特點(diǎn)、應(yīng)用場(chǎng)景以及與其他框架的對(duì)比。 一、引言 在當(dāng)今的前端開發(fā)領(lǐng)域,Vue.js已經(jīng)成為了一個(gè)備受矚目的框架。它的簡(jiǎn)潔、靈活和易于上手的特性使得開發(fā)人員能夠快速高效地構(gòu)建用戶

    2024年01月23日
    瀏覽(29)
  • redis到底是怎么樣進(jìn)行漸進(jìn)式Rehash的

    redis到底是怎么樣進(jìn)行漸進(jìn)式Rehash的

    Redis 是一個(gè)開源(BSD許可)的,內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)系統(tǒng),它可以用作數(shù)據(jù)庫(kù)、緩存和消息中間件。那么redis的底層是如何來(lái)存儲(chǔ)數(shù)據(jù)的呢? 一、redis如何在存儲(chǔ)大量的key時(shí)候,查詢速度還能接近O(1)呢? 查詢速度接近O(1)的數(shù)據(jù)結(jié)構(gòu)通常讓我們想到的就是HashMap結(jié)構(gòu),那下面

    2024年02月09日
    瀏覽(22)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包