亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

目錄 搜索
導(dǎo)論 前言 為什么學(xué)習(xí)JavaScript JavaScript的歷史 基本語(yǔ)法 語(yǔ)法概述 數(shù)值 字符串 對(duì)象 數(shù)組 函數(shù) 運(yùn)算符 數(shù)據(jù)類型轉(zhuǎn)換 錯(cuò)誤處理機(jī)制 JavaScript 編程風(fēng)格 標(biāo)準(zhǔn)庫(kù) Object對(duì)象 包裝對(duì)象和Boolean對(duì)象 Number對(duì)象 String對(duì)象 Math對(duì)象 Date對(duì)象 RegExp對(duì)象 JSON對(duì)象 ArrayBuffer:類型化數(shù)組 面向?qū)ο缶幊?/a> 概述 封裝 繼承 模塊化編程 DOM Node節(jié)點(diǎn) document節(jié)點(diǎn) Element對(duì)象 Text節(jié)點(diǎn)和DocumentFragment節(jié)點(diǎn) Event對(duì)象 CSS操作 Mutation Observer 瀏覽器對(duì)象 瀏覽器的JavaScript引擎 定時(shí)器 window對(duì)象 history對(duì)象 Ajax 同域限制和window.postMessage方法 Web Storage:瀏覽器端數(shù)據(jù)儲(chǔ)存機(jī)制 IndexedDB:瀏覽器端數(shù)據(jù)庫(kù) Web Notifications API Performance API 移動(dòng)設(shè)備API HTML網(wǎng)頁(yè)元素 Canvas API SVG 圖像 表單 文件和二進(jìn)制數(shù)據(jù)的操作 Web Worker 服務(wù)器發(fā)送事件 Page Visibility API Fullscreen API:全屏操作 Web Speech requestAnimationFrame WebSocket WebRTC Web Components HTML網(wǎng)頁(yè)的API HTML網(wǎng)頁(yè)元素 Canvas API SVG 圖像 表單 文件和二進(jìn)制數(shù)據(jù)的操作 Web Worker 服務(wù)器發(fā)送事件 Page Visibility API Fullscreen API:全屏操作 Web Speech requestAnimationFrame WebSocket WebRTC Web Components 開(kāi)發(fā)工具 console對(duì)象 PhantomJS Bower:客戶端庫(kù)管理工具 Grunt:任務(wù)自動(dòng)管理工具 Gulp:任務(wù)自動(dòng)管理工具 Browserify:瀏覽器加載Node.js模塊 RequireJS和AMD規(guī)范 Source Map JavaScript 程序測(cè)試 JavaScript高級(jí)語(yǔ)法 Promise對(duì)象 有限狀態(tài)機(jī) MVC框架與Backbone.js 嚴(yán)格模式 ECMAScript 6 介紹 附錄 JavaScript API列表
文字

    • 概述

    • 客戶端代碼

      • 概述

      • 建立連接

      • open事件

      • message事件

      • error事件

      • 自定義事件

      • close方法

    • 數(shù)據(jù)格式

      • 概述

      • data:數(shù)據(jù)欄

      • id:數(shù)據(jù)標(biāo)識(shí)符

      • event欄:自定義信息類型

      • retry:最大間隔時(shí)間

    • 服務(wù)器代碼

    • 參考鏈接

概述

傳統(tǒng)的網(wǎng)頁(yè)都是瀏覽器向服務(wù)器“查詢”數(shù)據(jù),但是很多場(chǎng)合,最有效的方式是服務(wù)器向?yàn)g覽器“發(fā)送”數(shù)據(jù)。比如,每當(dāng)收到新的電子郵件,服務(wù)器就向?yàn)g覽器發(fā)送一個(gè)“通知”,這要比瀏覽器按時(shí)向服務(wù)器查詢(polling)更有效率。

服務(wù)器發(fā)送事件(Server-Sent Events,簡(jiǎn)稱SSE)就是為了解決這個(gè)問(wèn)題,而提出的一種新API,部署在EventSource對(duì)象上。目前,除了IE,其他主流瀏覽器都支持。

簡(jiǎn)單說(shuō),所謂SSE,就是瀏覽器向服務(wù)器發(fā)送一個(gè)HTTP請(qǐng)求,然后服務(wù)器不斷單向地向?yàn)g覽器推送“信息”(message)。這種信息在格式上很簡(jiǎn)單,就是“信息”加上前綴“data: ”,然后以“\n\n”結(jié)尾。

$ curl http://example.com/dates
data: 1394572346452

data: 1394572347457

data: 1394572348463

^C

SSE與WebSocket有相似功能,都是用來(lái)建立瀏覽器與服務(wù)器之間的通信渠道。兩者的區(qū)別在于:

  • WebSocket是全雙工通道,可以雙向通信,功能更強(qiáng);SSE是單向通道,只能服務(wù)器向?yàn)g覽器端發(fā)送。

  • WebSocket是一個(gè)新的協(xié)議,需要服務(wù)器端支持;SSE則是部署在HTTP協(xié)議之上的,現(xiàn)有的服務(wù)器軟件都支持。

  • SSE是一個(gè)輕量級(jí)協(xié)議,相對(duì)簡(jiǎn)單;WebSocket是一種較重的協(xié)議,相對(duì)復(fù)雜。

  • SSE默認(rèn)支持?jǐn)嗑€重連,WebSocket則需要額外部署。

  • SSE支持自定義發(fā)送的數(shù)據(jù)類型。

從上面的比較可以看出,兩者各有特點(diǎn),適合不同的場(chǎng)合。

客戶端代碼

概述

首先,使用下面的代碼,檢測(cè)瀏覽器是否支持SSE。

if (!!window.EventSource) {
  // ...
}

然后,部署SSE大概如下。

var source = new EventSource('/dates');

source.onmessage = function(e){
  console.log(e.data);
};

// 或者

source.addEventListener('message', function(e){})

建立連接

首先,瀏覽器向服務(wù)器發(fā)起連接,生成一個(gè)EventSource的實(shí)例對(duì)象。

var source = new EventSource(url);

參數(shù)url就是服務(wù)器網(wǎng)址,必須與當(dāng)前網(wǎng)頁(yè)的網(wǎng)址在同一個(gè)網(wǎng)域(domain),而且協(xié)議和端口都必須相同。

下面是一個(gè)建立連接的實(shí)例。

if (!!window.EventSource) {
  var source = new EventSource('http://127.0.0.1/sses/');
}

新生成的EventSource實(shí)例對(duì)象,有一個(gè)readyState屬性,表明連接所處的狀態(tài)。

source.readyState

它可以取以下值:

  • 0,相當(dāng)于常量EventSource.CONNECTING,表示連接還未建立,或者連接斷線。

  • 1,相當(dāng)于常量EventSource.OPEN,表示連接已經(jīng)建立,可以接受數(shù)據(jù)。

  • 2,相當(dāng)于常量EventSource.CLOSED,表示連接已斷,且不會(huì)重連。

open事件

連接一旦建立,就會(huì)觸發(fā)open事件,可以定義相應(yīng)的回調(diào)函數(shù)。

source.onopen = function(event) {
  // handle open event
};

// 或者

source.addEventListener("open", function(event) {
  // handle open event
}, false);

message事件

收到數(shù)據(jù)就會(huì)觸發(fā)message事件。

source.onmessage = function(event) {
  var data = event.data;
  var origin = event.origin;
  var lastEventId = event.lastEventId;
  // handle message
};

// 或者

source.addEventListener("message", function(event) {
  var data = event.data;
  var origin = event.origin;
  var lastEventId = event.lastEventId;
  // handle message
}, false);

參數(shù)對(duì)象event有如下屬性:

  • data:服務(wù)器端傳回的數(shù)據(jù)(文本格式)。

  • origin: 服務(wù)器端URL的域名部分,即協(xié)議、域名和端口。

  • lastEventId:數(shù)據(jù)的編號(hào),由服務(wù)器端發(fā)送。如果沒(méi)有編號(hào),這個(gè)屬性為空。

error事件

如果發(fā)生通信錯(cuò)誤(比如連接中斷),就會(huì)觸發(fā)error事件。

source.onerror = function(event) {
  // handle error event
};

// 或者

source.addEventListener("error", function(event) {
  // handle error event
}, false);

自定義事件

服務(wù)器可以與瀏覽器約定自定義事件。這種情況下,發(fā)送回來(lái)的數(shù)據(jù)不會(huì)觸發(fā)message事件。

source.addEventListener("foo", function(event) {
  var data = event.data;
  var origin = event.origin;
  var lastEventId = event.lastEventId;
  // handle message
}, false);

上面代碼表示,瀏覽器對(duì)foo事件進(jìn)行監(jiān)聽(tīng)。

close方法

close方法用于關(guān)閉連接。

source.close();

數(shù)據(jù)格式

概述

服務(wù)器端發(fā)送的數(shù)據(jù)的HTTP頭信息如下:

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

后面的行都是如下格式:

field: value\n

field可以取四個(gè)值:“data”, “event”, “id”, or “retry”,也就是說(shuō)有四類頭信息。每次HTTP通信可以包含這四類頭信息中的一類或多類。\n代表?yè)Q行符。

以冒號(hào)開(kāi)頭的行,表示注釋。通常,服務(wù)器每隔一段時(shí)間就會(huì)向?yàn)g覽器發(fā)送一個(gè)注釋,保持連接不中斷。

: This is a comment

下面是一些例子。

: this is a test stream\n\n

data: some text\n\n

data: another message\n
data: with two lines \n\n

data:數(shù)據(jù)欄

數(shù)據(jù)內(nèi)容用data表示,可以占用一行或多行。如果數(shù)據(jù)只有一行,則像下面這樣,以“\n\n”結(jié)尾。

data:  message\n\n

如果數(shù)據(jù)有多行,則最后一行用“\n\n”結(jié)尾,前面行都用“\n”結(jié)尾。

data: begin message\n
data: continue message\n\n

總之,最后一行的data,結(jié)尾要用兩個(gè)換行符號(hào),表示數(shù)據(jù)結(jié)束。

以發(fā)送JSON格式的數(shù)據(jù)為例。

data: {\n
data: "foo": "bar",\n
data: "baz", 555\n
data: }\n\n

id:數(shù)據(jù)標(biāo)識(shí)符

數(shù)據(jù)標(biāo)識(shí)符用id表示,相當(dāng)于每一條數(shù)據(jù)的編號(hào)。

id: msg1\ndata: message\n\n

瀏覽器用lastEventId屬性讀取這個(gè)值。一旦連接斷線,瀏覽器會(huì)發(fā)送一個(gè)HTTP頭,里面包含一個(gè)特殊的“Last-Event-ID”頭信息,將這個(gè)值發(fā)送回來(lái),用來(lái)幫助服務(wù)器端重建連接。因此,這個(gè)頭信息可以被視為一種同步機(jī)制。

event欄:自定義信息類型

event頭信息表示自定義的數(shù)據(jù)類型,或者說(shuō)數(shù)據(jù)的名字。

event: foo\n
data: a foo event\n\n

data: an unnamed event\n\n

event: bar\n
data: a bar event\n\n

上面的代碼創(chuàng)造了三條信息。第一條是foo,觸發(fā)瀏覽器端的foo事件;第二條未取名,表示默認(rèn)類型,觸發(fā)瀏覽器端的message事件;第三條是bar,觸發(fā)瀏覽器端的bar事件。

retry:最大間隔時(shí)間

瀏覽器默認(rèn)的是,如果服務(wù)器端三秒內(nèi)沒(méi)有發(fā)送任何信息,則開(kāi)始重連。服務(wù)器端可以用retry頭信息,指定通信的最大間隔時(shí)間。

retry: 10000\n

服務(wù)器代碼

服務(wù)器端發(fā)送事件,要求服務(wù)器與瀏覽器保持連接。對(duì)于不同的服務(wù)器軟件來(lái)說(shuō),所消耗的資源是不一樣的。Apache服務(wù)器,每個(gè)連接就是一個(gè)線程,如果要維持大量連接,勢(shì)必要消耗大量資源。Node.js則是所有連接都使用同一個(gè)線程,因此消耗的資源會(huì)小得多,但是這要求每個(gè)連接不能包含很耗時(shí)的操作,比如磁盤(pán)的IO讀寫(xiě)。

下面是Node.js的服務(wù)器發(fā)送事件的代碼實(shí)例。

var http = require("http");

http.createServer(function (req, res) {    var fileName = "." + req.url;    if (fileName === "./stream") {
        res.writeHead(200, {"Content-Type":"text/event-stream", 
                            "Cache-Control":"no-cache", 
                            "Connection":"keep-alive"});
        res.write("retry: 10000\n");
        res.write("event: connecttime\n");
        res.write("data: " + (new Date()) + "\n\n");
        res.write("data: " + (new Date()) + "\n\n");

        interval = setInterval(function() {
            res.write("data: " + (new Date()) + "\n\n");
        }, 1000);

        req.connection.addListener("close", function () {
            clearInterval(interval);
        }, false);
  }
}).listen(80, "127.0.0.1");

PHP代碼實(shí)例。

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache'); // 建議不要緩存SSE數(shù)據(jù)

/**
 * Constructs the SSE data format and flushes that data to the client.
 *
 * @param string $id Timestamp/id of this connection.
 * @param string $msg Line of text that should be transmitted.
 */
function sendMsg($id, $msg) {
  echo "id: $id" . PHP_EOL;
  echo "data: $msg" . PHP_EOL;
  echo PHP_EOL;
  ob_flush();
  flush();
}

$serverTime = time();

sendMsg($serverTime, 'server time: ' . date("h:i:s", time()));
sendMsg($serverTime, 'server time: ' . date("h:i:s", time()));

參考鏈接


上一篇: 下一篇: