偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

可插拔的跨域聊天機器人實現(xiàn)方案復(fù)盤(postMessage版)

開發(fā) 前端
由于筆者之前的項目中接觸過聊天機器人的項目,主要實現(xiàn)機器人客服模塊,以及支持跨多平臺使用的目的,所以特地總結(jié)一下,希望有所收獲。

[[373659]]

由于筆者之前的項目中接觸過聊天機器人的項目,主要實現(xiàn)機器人客服模塊,以及支持跨多平臺使用的目的,所以特地總結(jié)一下,希望有所收獲。

你將學(xué)到

  • 跨域技術(shù)常用方案介紹
  • postMessage實現(xiàn)跨域通信
  • 如何實現(xiàn)聊天機器人
  • node搭建本地服務(wù)器來實現(xiàn)渲染頁面和跨域
  • 回答語料庫設(shè)計思路

效果預(yù)覽


正文

1. 跨域技術(shù)常用方案介紹

首先要強調(diào)的是跨域的安全限制都是對瀏覽器端來說的,服務(wù)器端是不存在跨域安全限制的。我們常用的跨域技術(shù)主要有如下幾種:

  • JSONP跨域
  • iframe+domain跨域
  • nginx反向代理跨域
  • cors跨域
  • postMessage跨域

JSONP實現(xiàn)跨域請求的原理就是動態(tài)創(chuàng)建script標(biāo)簽,然后利用script的src 不受同源策略約束來跨域獲取數(shù)據(jù)。JSONP 主要由回調(diào)函數(shù)和數(shù)據(jù)兩部分組成。回調(diào)函數(shù)的名字一般是在請求中指定的。而數(shù)據(jù)就是傳入回調(diào)函數(shù)中的 JSON 數(shù)據(jù)。我們一般可以在全局定義一個回調(diào)函數(shù),然后在script標(biāo)簽里傳入回調(diào)函數(shù)即可:

  1. window.handleData = function(data){ 
  2.     // ... 
  3. let script = document.createElement("script"); 
  4. script.src = "https://xxxx.com/v0/search?q=xuxi&callback=handleData"
  5. document.body.insertBefore(script, document.body.firstChild); 

這樣我們就能在回調(diào)函數(shù)handleData中拿到服務(wù)器接口返回的數(shù)據(jù)了。

雖然jsonp實現(xiàn)跨域方式很簡單,但是只支持get請求,對傳輸?shù)臄?shù)據(jù)量有一定限制。cors跨域是目前我們用的比較多的本地調(diào)試方式,原理就是在服務(wù)端設(shè)置響應(yīng)頭header的Access-Control-Allow-Origin字段,這樣瀏覽器檢測到header中的Access-Control-Allow-Origin,這樣就可以跨域了。

至于我們設(shè)置了cors之后在network中出現(xiàn)了兩次請求的問題,其實涉及到cors跨域的請求預(yù)檢,分為簡單請求和非簡單請求兩種,這塊知識可以單獨抽離出一篇文章,感興趣的可以自己學(xué)習(xí)了解一下。

2. postMessage實現(xiàn)跨域通信

  • window.postMessage() 方法可以安全地實現(xiàn)跨源通信。通常,對于兩個不同頁面的腳本,只有當(dāng)執(zhí)行它們的頁面位于具有相同的協(xié)議,端口號以及主機 (兩個頁面的模數(shù) Document.domain設(shè)置為相同的值) 時,這兩個腳本才能相互通信。window.postMessage() 方法提供了一種受控機制來規(guī)避此限制,只要正確的使用,這種方法就很安全。

本質(zhì)上說postMessage()是基于消息事件機制來實現(xiàn)跨域通信,它隸屬于消息窗體本身,比如window以及window內(nèi)嵌的frame的window,基本使用形式如下:

  1. someWindow.postMessage(message, targetOrigin, [transfer]); 

參數(shù)介紹:

  • someWindow 窗口的一個引用,比如iframe的contentWindow屬性、執(zhí)行window.open返回的窗口對象、或者是命名過或數(shù)值索引的window.frames
  • message 將要發(fā)送到其他 window的數(shù)據(jù)。意味著你可以不受什么限制的將數(shù)據(jù)對象安全的傳送給目標(biāo)窗口而無需自己序列化
  • targetOrigin 通過窗口的origin屬性來指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示無限制)。不提供確切的目標(biāo)將導(dǎo)致數(shù)據(jù)泄露等安全問題
  • transfer 是一串和message 同時傳遞的 Transferable 對象. 這些對象的所有權(quán)將被轉(zhuǎn)移給消息的接收方,而發(fā)送一方將不再保有所有權(quán)

我們可以通過如下方式來監(jiān)聽message:

  1. window.addEventListener("message", receiveMessage, false); 
  2.  
  3. function receiveMessage(event){ 
  4.   let origin = event.origin || event.originalEvent.origin;  
  5.   if (origin !== "http://aaa:8080"
  6.     return
  7.  
  8.   // ... 
  9.   console.log(event.data) 
  10.  
  11. // 派發(fā)消息的頁面 
  12. winB.postMessage(_({text: '休息休息'}), origin) 

我們的event里有如下幾個核心的屬性:

  • data 從其他 window 中傳遞過來的對象
  • origin 調(diào)用 postMessage 時消息發(fā)送方窗口的 origin . 這個字符串由 協(xié)議、“://“、域名、“ : 端口號”拼接而成
  • source 對發(fā)送消息的窗口對象的引用; 您可以使用此來在具有不同origin的兩個窗口之間建立雙向通信

3. 實現(xiàn)聊天機器人

在熟悉以上知識點之后,我們開始來寫我們聊天機器人的demo。首先我們寫兩個html,分別為a.html和b.html,然后用node分別代理兩個不同頁面,設(shè)置不同端口:

  1. // a.js 
  2. //依賴一個http模塊,相當(dāng)于java中的import,與C#中的using 
  3. var http = require('http'); 
  4. var fs = require('fs'); 
  5. var { resolve } = require('path'); 
  6.  
  7. //創(chuàng)建一個服務(wù)器對象 
  8. server = http.createServer(function (req, res) { 
  9. //設(shè)置請求成功時響應(yīng)頭部的MIME為純文本 
  10. res.writeHeader(200, {"Content-Type""text/html"}); 
  11. //向客戶端輸出字符 
  12. let data = fs.readFileSync(resolve(__dirname, './a.html')) 
  13. res.end(data); 
  14. }); 
  15. //讓服務(wù)器監(jiān)聽本地8000端口開始運行 
  16. server.listen(8000,'127.0.0.1'); 
  17. console.log('http://127.0.0.1:8000'
  18.  
  19. // b.js 
  20. // ... 
  21. server.listen(8001,'127.0.0.1'); 

由上可知我們a.html代理在8000端口下,b.html代理在8001端口下,由瀏覽器的同源策略可知他們存在跨域問題。

跨域?qū)崿F(xiàn)之后我們可以開始搭建頁面層級了,我們這里將b頁面以iframe的形式嵌入到a頁面,具體結(jié)構(gòu)如下:


這樣我們就可以愉快的搭建postMessage體系了。首先我們在a頁面通過發(fā)送按鈕和輸入框?qū)⑾l(fā)送給b頁面,大致結(jié)構(gòu)如下:

  1. <body> 
  2.     <div class="wrap"
  3.         <iframe src="http://127.0.0.1:8001" frameborder="0" id="b"></iframe> 
  4.         <div class="control"
  5.             <input type="text" placeholder="請輸入內(nèi)容" id="ipt"
  6.             <span id="send">發(fā)送</span> 
  7.         </div> 
  8.     </div> 
  9.     <script> 
  10.         window.onload = function() { 
  11.             let origin = 'http://127.0.0.1:8001'
  12.             let _ = (data) => JSON.stringify(data); 
  13.             let winB = document.querySelector('#b').contentWindow; 
  14.             let sendBtn = document.querySelector('#send'); 
  15.             sendBtn.addEventListener('click', (e) => { 
  16.                 let text = document.querySelector('#ipt'); 
  17.                 winB.postMessage(_({text: text.value}), origin) 
  18.                 text.value = ''
  19.             }, false
  20.             winB.postMessage(_({text: ''}), origin) 
  21.         } 
  22.     </script> 
  23. </body> 

 我們可以通過iframe的contentWindow來拿到b頁面窗體的引用,然后在發(fā)送按鈕的點擊事件中觸發(fā)postMessage將數(shù)據(jù)發(fā)送給B。B頁面結(jié)構(gòu)如下:

  1. <body> 
  2.     <div class="content"
  3.             <h4>Lab智能機器人</h4> 
  4.             <div class="content-inner"></div> 
  5.     </div> 
  6.     <script> 
  7.         // 語料庫 
  8.         const pool = []; 
  9.         window.addEventListener("message", receiveMessage, false); 
  10.         let content = document.querySelector('.content-inner'); 
  11.         let initContentH = content.scrollHeight; 
  12.         let _ = (data) => JSON.stringify(data); 
  13.         function createChat(type, mes) { 
  14.             let dialog = document.createElement('div'); 
  15.             dialog.className = type === 0 ? 'dialog robot' : 'dialog user'
  16.             let content =  type === 0 ? ` 
  17.                 <span class="tx">${type === 0 ? 'lab' : 'user'}</span> 
  18.                 <span class="mes">${mes}</span> 
  19.             ` : ` 
  20.                 <span class="mes">${mes}</span> 
  21.                 <span class="tx">${type === 0 ? 'lab' : 'user'}</span>  
  22.             `; 
  23.             dialog.innerHTML = content; 
  24.             return dialog 
  25.         } 
  26.  
  27.         function scrollTop(el, h) { 
  28.             if(el.scrollHeight !== h) { 
  29.                 el.scrollTop = h + 100; 
  30.             } 
  31.         } 
  32.  
  33.         function receiveMessage(event){ 
  34.             // 兼容其他瀏覽器 
  35.             let origin = event.origin || event.originalEvent.origin;  
  36.             if(origin === 'http://127.0.0.1:8000') { 
  37.                 let data = JSON.parse(event.data); 
  38.                 if(data && !data.text) { 
  39.                     mes = { text: '你好,我是機器人Lab,請問有什么可以幫到您的嗎?' }; 
  40.                     event.source.postMessage(_(mes), event.origin) 
  41.                     content.appendChild(createChat(0, mes.text)) 
  42.                      
  43.                 }else { 
  44.                     content.appendChild(createChat(1, data.text)) 
  45.                     scrollTop(content, initContentH) 
  46.                      
  47.                     setTimeout(() => { 
  48.                          
  49.                         content.appendChild(createChat(0, '正在解決')) 
  50.                         scrollTop(content, initContentH) 
  51.                     }, 2000); 
  52.                 }  
  53.             } 
  54.         } 
  55.     </script> 
  56. </body> 
 我們在b頁面中去解析a頁面的數(shù)據(jù)并做出相應(yīng)的回答。這樣,我們的基本聊天機器人就實現(xiàn)了。

4. 回答語料庫設(shè)計思路

至于當(dāng)我們在a頁面發(fā)送了一個消息,b頁面如何解析并回答,可以有如下幾種思路:

  • 通過后端接口實現(xiàn),即我們可以將a的數(shù)據(jù)作為參數(shù)傳遞給某個后端接口,讓后端來實現(xiàn)返回需要的數(shù)據(jù),這種在AI機器人中應(yīng)用的很廣泛。
  • 純前端實現(xiàn)。前端定義回答的語料庫,通過關(guān)鍵詞匹配來拿到實現(xiàn)應(yīng)答,這種一般用于普通的預(yù)設(shè)問題的回答。

5.實現(xiàn)可插拔式

可插拔式就是一個頁面可以放在不同平臺使用。這種我們可以設(shè)置origin白名單,只需要將b頁面封裝,其他系統(tǒng)可以使用類于a頁面的方式,只提供發(fā)送信息的接口,這樣我們就可以在不同平使用了。


在 H5-dooring 項目中也使用了客服機器人 chatbot-antd, 感興趣可以了解一下.

 

責(zé)任編輯:姜華 來源: 趣談前端
相關(guān)推薦

2022-07-05 06:42:01

聊天機器人人工智能

2023-10-29 21:20:04

谷歌Bard聊天機器人

2017-03-28 12:21:21

機器人定義

2016-02-16 14:46:33

聊天機器人機器學(xué)習(xí)自然語言

2020-02-02 09:19:14

聊天機器人機器人智能

2025-06-04 08:21:28

2023-06-29 15:04:21

微軟ChatGPT

2023-12-18 19:05:34

2019-12-19 16:08:40

人工智能機器人數(shù)據(jù)

2022-07-03 10:23:06

機器人場景個性化

2017-08-21 13:31:44

AI聊天機器人facebook

2019-06-04 08:00:00

機器人聊天機器人人工智能

2023-04-27 08:00:00

2019-07-03 10:02:47

聊天機器人平臺機器人

2020-02-20 09:00:00

網(wǎng)絡(luò)應(yīng)用數(shù)據(jù)技術(shù)

2023-05-18 10:06:00

聊天機器人醫(yī)療保健

2024-11-01 07:30:00

2019-07-30 07:53:08

機器人人工智能系統(tǒng)

2023-08-23 08:54:59

OpenAIGPT-3.5
點贊
收藏

51CTO技術(shù)棧公眾號