全面分析前端的網絡請求方式

1、前端進行網絡請求的關注點

大多數狀況下,在前端發起一個網絡請求咱們只需關注下面幾點:html

  • 傳入基本參數(url,請求方式)
  • 請求參數、請求參數類型
  • 設置請求頭
  • 獲取響應的方式
  • 獲取響應頭、響應狀態、響應結果
  • 異常處理
  • 攜帶cookie設置
  • 跨域請求

2、前端進行網絡請求的方式

  • form表單、ifream、刷新頁面
  • Ajax - 異步網絡請求的開山鼻祖
  • jQuery - 一個時代
  • fetch - Ajax的替代者
  • axios、request等衆多開源庫

3、關於網絡請求的疑問

  • Ajax的出現解決了什麼問題
  • 原生Ajax如何使用
  • jQuery的網絡請求方式
  • fetch的用法以及坑點
  • 如何正確的使用fetch
  • 如何選擇合適的跨域方式

帶着以上這些問題、關注點咱們對幾種網絡請求進行一次全面的分析。前端

4、Ajax的出現解決了什麼問題

Ajax出現以前,web程序是這樣工做的:node

image

這種交互的的缺陷是顯而易見的,任何和服務器的交互都須要刷新頁面,用戶體驗很是差,Ajax的出現解決了這個問題。Ajax全稱Asynchronous JavaScript + XML(異步JavaScriptXMLjquery

使用Ajax,網頁應用可以快速地將增量更新呈如今用戶界面上,而不須要重載(刷新)整個頁面。ios

Ajax自己不是一種新技術,而是用來描述一種使用現有技術集合實現的一個技術方案,瀏覽器的XMLHttpRequest是實現Ajax最重要的對象(IE6如下使用ActiveXObject)。nginx

儘管XAjax中表明XML, 但因爲JSON的許多優點,好比更加輕量以及做爲Javascript的一部分,目前JSON的使用比XML更加廣泛。git

5、原生Ajax的用法

這裏主要分析XMLHttpRequest對象,下面是它的一段基礎使用:github

var xhr = new XMLHttpRequest();
        xhr.open('post','www.xxx.com',true)
        // 接收返回值
        xhr.onreadystatechange = function(){
            if(xhr.readyState === 4 ){
                if(xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
                    console.log(xhr.responseText);
                }
            }
        }
        // 處理請求參數
        postData = {"name1":"value1","name2":"value2"};
        postData = (function(value){
        var dataString = "";
        for(var key in value){
             dataString += key+"="+value[key]+"&";
        };
          return dataString;
        }(postData));
        // 設置請求頭
        xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
        // 異常處理
        xhr.onerror = function() {
           console.log('Network request failed')
        }
        // 跨域攜帶cookie
        xhr.withCredentials = true;
        // 發出請求
        xhr.send(postData);
複製代碼

下面分別對XMLHttpRequest對象經常使用的的函數、屬性、事件進行分析。web

image

函數

openajax

用於初始化一個請求,用法:

xhr.open(method, url, async);
複製代碼
  • method:請求方式,如get、post
  • url:請求的url
  • async:是否爲異步請求

send

用於發送HTTP請求,即調用該方法後HTTP請求才會被真正發出,用法:

xhr.send(param)
複製代碼
  • param:http請求的參數,能夠爲string、Blob等類型。

abort

用於終止一個ajax請求,調用此方法後readyState將被設置爲0,用法:

xhr.abort()
複製代碼

setRequestHeader

用於設置HTTP請求頭,此方法必須在open()方法和send()之間調用,用法:

xhr.setRequestHeader(header, value);
複製代碼

getResponseHeader

用於獲取http返回頭,若是在返回頭中有多個同樣的名稱,那麼返回的值就會是用逗號和空格將值分隔的字符串,用法:

var header = xhr.getResponseHeader(name);
複製代碼

屬性

readyState

用來標識當前XMLHttpRequest對象所處的狀態,XMLHttpRequest對象老是位於下列狀態中的一個:

狀態 描述
0 UNSENT 代理被建立,但還沒有調用 open() 方法。
1 OPENED open() 方法已經被調用。
2 HEADERS_RECEIVED send()方法已經被調用,而且頭部和狀態已經可得到。
3 LOADING 下載中; responseText 屬性已經包含部分數據。
4 DONE 下載操做已完成。

status

表示http請求的狀態, 初始值爲0。若是服務器沒有顯式地指定狀態碼, 那麼status將被設置爲默認值, 即200

responseType

表示響應的數據類型,並容許咱們手動設置,若是爲空,默認爲text類型,能夠有下面的取值:

描述
"" responseType設爲空字符串與設置爲"text"相同, 是默認類型 (其實是 DOMString)。
"arraybuffer" response 是一個包含二進制數據的JavaScript ArrayBuffer
"blob" response是一個包含二進制數據的 Blob 對象 。
"document" response 是一個HTML DocumentXML XMLDocument,這取決於接收到的數據的 MIME 類型。
"json" response 是一個 JavaScript 對象。這個對象是經過將接收到的數據類型視爲JSON解析獲得的。
"text" response是包含在DOMString對象中的文本。

response

返回響應的正文,返回的類型由上面的responseType決定。

withCredentials

ajax請求默認會攜帶同源請求的cookie,而跨域請求則不會攜帶cookie,設置xhrwithCredentials的屬性爲true將容許攜帶跨域cookie

事件回調

onreadystatechange

xhr.onreadystatechange = callback;
複製代碼

readyState屬性發生變化時,callback會被觸發。

onloadstart

xhr.onloadstart = callback;
複製代碼

ajax請求發送以前(readyState==1後, readyState==2前),callback會被觸發。

onprogress

xhr.onprogress = function(event){
  console.log(event.loaded / event.total);
}
複製代碼

回調函數能夠獲取資源總大小total,已經加載的資源大小loaded,用這兩個值能夠計算加載進度。

onload

xhr.onload = callback;
複製代碼

當一個資源及其依賴資源已完成加載時,將觸發callback,一般咱們會在onload事件中處理返回值。

異常處理

onerror

xhr.onerror = callback;
複製代碼

ajax資源加載失敗時會觸發callback

ontimeout

xhr.ontimeout = callback;
複製代碼

當進度因爲預約時間到期而終止時,會觸發callback,超時時間可以使用timeout屬性進行設置。

6、jQuery對Ajax的封裝

在很長一段時間裏,人們使用jQuery提供的ajax封裝進行網絡請求,包括$.ajax、$.get、$.post等,這幾個方法放到如今,我依然以爲很實用。

$.ajax({
    dataType: 'json', // 設置返回值類型
    contentType: 'application/json', // 設置參數類型
    headers: {'Content-Type','application/json'},// 設置請求頭
    xhrFields: { withCredentials: true }, // 跨域攜帶cookie
    data: JSON.stringify({a: [{b:1, a:1}]}), // 傳遞參數
    error:function(xhr,status){  // 錯誤處理
       console.log(xhr,status);
    },
    success: function (data,status) {  // 獲取結果
       console.log(data,status);
    }
})
複製代碼

$.ajax只接收一個參數,這個參數接收一系列配置,其本身封裝了一個jqXHR對象,有興趣能夠閱讀一下jQuary-ajax 源碼

image

經常使用配置:

url

當前頁地址。發送請求的地址。

type

類型:String 請求方式 ("POST""GET"), 默認爲 "GET"。注意:其它HTTP請求方法,如PUTDELETE也可使用,但僅部分瀏覽器支持。

timeout

類型:Number設置請求超時時間(毫秒)。此設置將覆蓋全局設置。

success

類型:Function 請求成功後的回調函數。

jsonp

在一個jsonp請求中重寫回調函數的名字。這個值用來替代在"callback=?"這種GETPOST請求中URL參數裏的"callback"部分。

error 類型:Function 。請求失敗時調用此函數。

注意:源碼裏對錯誤的斷定:

isSuccess = status >= 200 && status < 300 || status === 304;
複製代碼

返回值除了這幾個狀態碼都會進error回調。

dataType

"xml": 返回 XML 文檔,可用 jQuery 處理。
"html": 返回純文本 HTML 信息;包含的 script 標籤會在插入 dom 時執行。
"script": 返回純文本 JavaScript 代碼。不會自動緩存結果。除非設置了 "cache" 參數。注意:在遠程請求時(不在同一個域下),全部 POST 請求都將轉爲 GET 請求。(由於將使用 DOM 的 script標籤來加載)
"json": 返回 JSON 數據 。
"jsonp": JSONP 格式。使用 JSONP 形式調用函數時,如 "myurl?callback=?" jQuery 將自動替換 ? 爲正確的函數名,以執行回調函數。
"text": 返回純文本字符串
複製代碼

data

類型:String 使用JSON.stringify轉碼

complete

類型:Function請求完成後回調函數 (請求成功或失敗以後均調用)。

async

類型:Boolean 默認值:true。默認設置下,全部請求均爲異步請求。若是須要發送同步請求,請將此選項設置爲 false

contentType

類型:String默認值: "application/x-www-form-urlencoded"。發送信息至服務器時內容編碼類型。

鍵值對這樣組織在通常的狀況下是沒有什麼問題的,這裏說的通常是,不帶嵌套類型JSON,也就是 簡單的JSON,形如這樣:

{
    a: 1,
    b: 2,
    c: 3
}
複製代碼

可是在一些複雜的狀況下就有問題了。 例如在 Ajax中你要傳一個複雜的 json 對像,也就說是對象嵌數組,數組中包括對象,你這樣傳:application/x-www-form-urlencoded 這種形式是沒有辦法將複雜的JSON組織成鍵值對形式。

{
  data: {
    a: [{
      x: 2
    }]
  }
}
複製代碼

能夠用以下方式傳遞複雜的json對象

$.ajax({
    dataType: 'json',
    contentType: 'application/json',
    data: JSON.stringify({a: [{b:1, a:1}]})
})
複製代碼

7、jQuery的替代者

近年來前端MV*的發展壯大,人們愈來愈少的使用jQuery,咱們不可能單獨爲了使用jQueryAjax api來單獨引入他,無可避免的,咱們須要尋找新的技術方案。

尤雨溪在他的文檔中推薦你們用axios進行網絡請求。axios基於Promise對原生的XHR進行了很是全面的封裝,使用方式也很是的優雅。另外,axios一樣提供了在node環境下的支持,可謂是網絡請求的首選方案。

將來一定還會出現更優秀的封裝,他們有很是周全的考慮以及詳細的文檔,這裏咱們很少作考究,咱們把關注的重點放在更底層的APIfetch

Fetch API是一個用用於訪問和操縱HTTP管道的強大的原生 API。

這種功能之前是使用 XMLHttpRequest實現的。Fetch提供了一個更好的替代方法,能夠很容易地被其餘技術使用,例如 Service Workers。Fetch還提供了單個邏輯位置來定義其餘HTTP相關概念,例如CORS和HTTP的擴展。

可見fetch是做爲XMLHttpRequest的替代品出現的。

使用fetch,你不須要再額外加載一個外部資源。但它尚未被瀏覽器徹底支持,因此你仍然須要一個polyfill

8、fetch的使用

一個基本的 fetch請求:

const options = {
    method: "POST", // 請求參數
    headers: { "Content-Type": "application/json"}, // 設置請求頭
    body: JSON.stringify({name:'123'}), // 請求參數
    credentials: "same-origin", // cookie設置
    mode: "cors", // 跨域
}
fetch('http://www.xxx.com',options)
  .then(function(response) {
    return response.json();
  })
  .then(function(myJson) {
    console.log(myJson); // 響應數據
  })
  .catch(function(err){
    console.log(err); // 異常處理
  })
複製代碼

Fetch API提供了一個全局的fetch()方法,以及幾個輔助對象來發起一個網絡請求。

image

  • fetch()

fetch()方法用於發起獲取資源的請求。它返回一個promise,這個 promise 會在請求響應後被 resolve,並傳回 Response 對象。

  • Headers

能夠經過Headers()構造函數來建立一個你本身的headers對象,至關於 response/request 的頭信息,可使你查詢到這些頭信息,或者針對不一樣的結果作不一樣的操做。

var myHeaders = new Headers();
myHeaders.append("Content-Type", "text/plain");
複製代碼
  • Request

經過Request()構造函數能夠建立一個Request對象,這個對象能夠做爲fetch函數的第二個參數。

  • Response

fetch()處理完promises以後返回一個Response實例,也能夠手動建立一個Response實例。

9、fetch polyfill源碼分析

因爲fetch是一個很是底層的API,因此咱們沒法進一步的探究它的底層,可是咱們能夠藉助它的polyfill探究它的基本原理,並找出其中的坑點。

代碼結構

image

由代碼可見,polyfill主要對Fetch API提供的四大對象進行了封裝:

fetch 封裝

image

代碼很是清晰:

  • 構造一個Promise對象並返回
  • 建立一個Request對象
  • 建立一個XMLHttpRequest對象
  • 取出Request對象中的請求url,請求方發,open一個xhr請求,並將Request對象中存儲的headers取出賦給xhr
  • xhr onload後取出responsestatusheadersbody封裝Response對象,調用resolve

異常處理

image

能夠發現,調用reject有三種可能:

  • 1.請求超時

  • 2.請求失敗

注意:當和服務器創建簡介,並收到服務器的異常狀態碼如40四、500等並不能觸發onerror。當網絡故障時或請求被阻止時,纔會標記爲 reject,如跨域、url不存在,網絡異常等會觸發onerror

因此使用fetch當接收到異常狀態碼都是會進入then而不是catch。這些錯誤請求每每要手動處理。

  • 3.手動終止

能夠在request參數中傳入signal對象,並對signal對象添加abort事件監聽,當xhr.readyState變爲4(響應內容解析完成)後將signal對象的abort事件監聽移除掉。

這表示,在一個fetch請求結束以前能夠調用signal.abort將其終止。在瀏覽器中可使用AbortController()構造函數建立一個控制器,而後使用AbortController.signal屬性

這是一個實驗中的功能,此功能某些瀏覽器尚在開發中

Headers封裝

image

在header對象中維護了一個map對象,構造函數中能夠傳入Header對象、數組、普通對象類型的header,並將全部的值維護到map中。

以前在fetch函數中看到調用了headerforEach方法,下面是它的實現:

image

可見header的遍歷即其內部map的遍歷。

另外Header還提供了append、delete、get、set等方法,都是對其內部的map對象進行操做。

Request對象

image

Request對象接收的兩個參數即fetch函數接收的兩個參數,第一個參數能夠直接傳遞url,也能夠傳遞一個構造好的request對象。第二個參數即控制不一樣配置的option對象。

能夠傳入credentials、headers、method、mode、signal、referrer等屬性。

這裏注意:

  • 傳入的headers被看成Headers構造函數的參數來構造header對象。

cookie處理

fetch函數中還有以下的代碼:

if (request.credentials === 'include') {
      xhr.withCredentials = true
    } else if (request.credentials === 'omit') {
      xhr.withCredentials = false
    }
複製代碼

默認的credentials類型爲same-origin,便可攜帶同源請求的coodkie。

而後我發現這裏polyfill的實現和MDN-使用Fetch以及不少資料是不一致的:

mdn: 默認狀況下,fetch 不會從服務端發送或接收任何 cookies

因而我分別實驗了下使用polyfill和使用原生fetch攜帶cookie的狀況,發如今不設置credentials的狀況下竟然都是默認攜帶同源cookie的,這和文檔的說明說不一致的,查閱了許多資料後都是說fetch默認不會攜帶cookie,下面是使用原生fetch在瀏覽器進行請求的狀況:

image

而後我發如今MDN-Fetch-Request已經指出新版瀏覽器credentials默認值已更改成same-origin,舊版依然是omit

確實MDN-使用Fetch這裏的文檔更新的有些不及時,誤人子弟了...

Response對象

Response對象是fetch調用成功後的返回值:

回顧下fetch中對Response`的操做:

xhr.onload = function () {
      var options = {
        status: xhr.status,
        statusText: xhr.statusText,
        headers: parseHeaders(xhr.getAllResponseHeaders() || '')
      }
      options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')
      var body = 'response' in xhr ? xhr.response : xhr.responseText
      resolve(new Response(body, options))
    }
複製代碼

Response構造函數:

image

可見在構造函數中主要對options中的status、statusText、headers、url等分別作了處理並掛載到Response對象上。

構造函數裏面並無對responseText的明確處理,最後交給了_initBody函數處理,而Response並無主動聲明_initBody屬性,代碼最後使用Response調用了Body函數,實際上_initBody函數是經過Body函數掛載到Response身上的,先來看看_initBody函數:

image

可見,_initBody函數根據xhr.response的類型(Blob、FormData、String...),爲不一樣的參數進行賦值,這些參數在Body方法中獲得不一樣的應用,下面具體看看Body函數還作了哪些其餘的操做:

image

Body函數中還爲Response對象掛載了四個函數,text、json、blob、formData,這些函數中的操做就是將_initBody中獲得的不一樣類型的返回值返回。

這也說明了,在fetch執行完畢後,不能直接在response中獲取到返回值而必須調用text()、json()等函數才能獲取到返回值。

這裏還有一點須要說明:幾個函數中都有相似下面的邏輯:

var rejected = consumed(this)
    if (rejected) {
      return rejected
    }
複製代碼

consumed函數:

function consumed(body) {
  if (body.bodyUsed) {
    return Promise.reject(new TypeError('Already read'))
  }
  body.bodyUsed = true
}
複製代碼

每次調用text()、json()等函數後會將bodyUsed變量變爲true,用來標識返回值已經讀取過了,下一次再讀取直接拋出TypeError('Already read')。這也遵循了原生fetch的原則:

由於Responses對象被設置爲了 stream 的方式,因此它們只能被讀取一次

10、fetch的坑點

VUE的文檔中對fetch有下面的描述:

使用fetch還有不少別的注意事項,這也是爲何你們現階段仍是更喜歡axios 多一些。固然這個事情在將來可能會發生改變。

因爲fetch是一個很是底層的API,它並無被進行不少封裝,還有許多問題須要處理:

  • 不能直接傳遞JavaScript對象做爲參數
  • 須要本身判斷返回值類型,並執行響應獲取返回值的方法
  • 獲取返回值方法只能調用一次,不能屢次調用
  • 沒法正常的捕獲異常
  • 老版瀏覽器不會默認攜帶cookie
  • 不支持jsonp

11、對fetch的封裝

請求參數處理

支持傳入不一樣的參數類型:

function stringify(url, data) {
  var dataString = url.indexOf('?') == -1 ? '?' : '&';
  for (var key in data) {
    dataString += key + '=' + data[key] + '&';
  };
  return dataString;
}

if (request.formData) {
  request.body = request.data;
} else if (/^get$/i.test(request.method)) {
  request.url = `${request.url}${stringify(request.url, request.data)}`;
} else if (request.form) {
  request.headers.set('Content-Type', 'application/x-www-form-urlencoded;charset=UTF-8');
  request.body = stringify(request.data);
} else {
  request.headers.set('Content-Type', 'application/json;charset=UTF-8');
  request.body = JSON.stringify(request.data);
}
複製代碼

cookie攜帶

fetch在新版瀏覽器已經開始默認攜帶同源cookie,但在老版瀏覽器中不會默認攜帶,咱們須要對他進行統一設置:

request.credentials =  'same-origin'; // 同源攜帶
  request.credentials =  'include'; // 可跨域攜帶
複製代碼

異常處理

當接收到一個表明錯誤的 HTTP 狀態碼時,從 fetch()返回的 Promise 不會被標記爲 reject, 即便該 HTTP 響應的狀態碼是 404 或 500。相反,它會將 Promise 狀態標記爲 resolve (可是會將 resolve 的返回值的 ok 屬性設置爲 false ),僅當網絡故障時或請求被阻止時,纔會標記爲 reject。

所以咱們要對fetch的異常進行統一處理

.then(response => {
  if (response.ok) {
    return Promise.resolve(response);
  }else{
    const error = new Error(`請求失敗! 狀態碼: ${response.status}, 失敗信息: ${response.statusText}`);
    error.response = response;
    return Promise.reject(error);
  }
});
複製代碼

返回值處理

對不一樣的返回值類型調用不一樣的函數接收,這裏必須提早判斷好類型,不能屢次調用獲取返回值的方法:

.then(response => {
  let contentType = response.headers.get('content-type');
  if (contentType.includes('application/json')) {
    return response.json();
  } else {
    return response.text();
  }
});
複製代碼

jsonp

fetch自己沒有提供對jsonp的支持,jsonp自己也不屬於一種很是好的解決跨域的方式,推薦使用cors或者nginx解決跨域,具體請看下面的章節。

fetch封裝好了,能夠愉快的使用了。

嗯,axios真好用...

12、跨域總結

談到網絡請求,就不得不提跨域。

瀏覽器的同源策略限制了從同一個源加載的文檔或腳本如何與來自另外一個源的資源進行交互。這是一個用於隔離潛在惡意文件的重要安全機制。一般不容許不一樣源間的讀操做。

跨域條件:協議,域名,端口,有一個不一樣就算跨域。

下面是解決跨域的幾種方式:

nginx

使用nginx反向代理實現跨域,參考我這篇文章:前端開發者必備的nginx知識

cors

CORS是一個W3C標準,全稱是"跨域資源共享"(Cross-origin resource sharing)。它容許瀏覽器向跨源服務器,發出XMLHttpRequest請求。

服務端設置Access-Control-Allow-Origin就能夠開啓CORS。 該屬性表示哪些域名能夠訪問資源,若是設置通配符則表示全部網站均可以訪問資源。

app.all('*', function (req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
    next();
});
複製代碼

jsonp

script標籤的src屬性中的連接能夠訪問跨域的js腳本,利用這個特性,服務端再也不返回JSON格式的數據,而是返回一段調用某個函數的js代碼,在src中進行了調用,這樣實現了跨域。

jqueryjsonp的支持:

$.ajax({
            type : "get",
            url : "http://xxxx"
            dataType: "jsonp",
            jsonp:"callback", 
            jsonpCallback: "doo",
            success : function(data) {
                console.log(data);
            }
        });
複製代碼

fetch、axios等並無直接提供對jsonp的支持,若是須要使用這種方式,咱們能夠嘗試進行手動封裝:

(function (window,document) {
 "use strict";
    var jsonp = function (url,data,callback) {

        // 1.將傳入的data數據轉化爲url字符串形式
        // {id:1,name:'jack'} => id=1&name=jack
        var dataString = url.indexof('?') == -1? '?': '&';
        for(var key in data){
            dataString += key + '=' + data[key] + '&';
        };

        // 2 處理url中的回調函數
        // cbFuncName回調函數的名字 :my_json_cb_名字的前綴 + 隨機數(把小數點去掉)
        var cbFuncName = 'my_json_cb_' + Math.random().toString().replace('.','');
        dataString += 'callback=' + cbFuncName;

        // 3.建立一個script標籤並插入到頁面中
        var scriptEle = document.createElement('script');
        scriptEle.src = url + dataString;

        // 4.掛載回調函數
        window[cbFuncName] = function (data) {
            callback(data);
            // 處理完回調函數的數據以後,刪除jsonp的script標籤
            document.body.removeChild(scriptEle);
        }

        document.body.appendChild(scriptEle);
    }

    window.$jsonp = jsonp;

})(window,document)
複製代碼

postMessage跨域

postMessage()方法容許來自不一樣源的腳本採用異步方式進行有限的通訊,能夠實現跨文本檔、多窗口、跨域消息傳遞。

//捕獲iframe
var domain = 'http://scriptandstyle.com';
var iframe = document.getElementById('myIFrame').contentWindow;

//發送消息
setInterval(function(){
	var message = 'Hello! The time is: ' + (new Date().getTime());
	console.log('blog.local: sending message: ' + message);
        //send the message and target URI
	iframe.postMessage(message,domain); 
},6000);
複製代碼
//響應事件
window.addEventListener('message',function(event) {
	if(event.origin !== 'http://davidwalsh.name') return;
	console.log('message received: ' + event.data,event);
	event.source.postMessage('holla back youngin!',event.origin);
},false);
複製代碼

postMessage跨域適用於如下場景:同瀏覽器多窗口間跨域通訊、iframe間跨域通訊。

WebSocket

WebSocket 是一種雙向通訊協議,在創建鏈接以後,WebSocketserverclient都能主動向對方發送或接收數據而不受同源策略的限制。

function WebSocketTest(){
            if ("WebSocket" in window){
               alert("您的瀏覽器支持 WebSocket!");
               // 打開一個 web socket
               var ws = new WebSocket("ws://localhost:3000/abcd");
               ws.onopen = function(){
                  // Web Socket 已鏈接上,使用 send() 方法發送數據
                  ws.send("發送數據");
                  alert("數據發送中...");
               };
               ws.onmessage = function (evt) { 
                  var received_msg = evt.data;
                  alert("數據已接收...");
               };
               ws.onclose = function(){ 
                  // 關閉 websocket
                  alert("鏈接已關閉..."); 
               };
            } else{
               // 瀏覽器不支持 WebSocket
               alert("您的瀏覽器不支持 WebSocket!");
            }
         }
複製代碼

文章首發

想閱讀更多優質文章,或者須要文章中思惟導圖源文件可關注個人github博客,歡迎star✨。

推薦你們使用Fundebug,一款很好用的BUG監控工具~

文中若有錯誤,歡迎在評論區指正,謝謝閱讀。

關注公衆號後回覆【加羣】拉你進入優質前端交流羣。

相關文章
相關標籤/搜索