1. 程式人生 > 其它 >session_start(): Cannot start session when headers already sent in

session_start(): Cannot start session when headers already sent in

服務端渲染

談起服務端渲染,對於動態服務而言,這個世界上跑的大多數頁面都經歷過服務端的資料渲染,介面->前端賦值->模版渲染 。這一切都在伺服器完成,我們檢視原始碼時候,可以看到完整的html程式碼,包括每個資料值。

常用的php模版有,Smarty,Blade,Mustache,如果你們團隊使用Smarty,我們可以看到一些view的檔案裡會前套Smarty的模版語言;

<div>  
{foreach $list as $item}
    <h3>{$item['name']}</h3>
    <p>{$item['desc']}</p>
{/foreach}
</div>

如果Node,js作為服務端的話,這個時候我們可以使用前端模版渲染的模組,比如ejs,doT,jade等等。

注意不同的模版可能存在不同模版語法,需要自己學習使用

AJAX

當然服務端渲染隨著單頁應用以及Restful介面的興起,Ajax逐漸成為目前前後端交流最為頻繁的方式。Ajax實際核心是XmlHttpRequest,我們通過對該物件的操作來進行非同步的資料請求。

// 一般流程
var oReq = new XMLHttpRequest();  
oReq.addEventListener("load", function(res) {  
    // your code to do something
});
oReq.open("GET", "http://www.example.org/example.txt");  
oReq.send();

實際上我們接觸到最多jQuey就有很好的封裝,比如$.ajax,$.post等,如果用Angular的話我們可以用$http服務,除了這些之外,我們可以使用第三方的Ajax庫qwest等。

如果使用Ajax的話,我們不得不面臨一些問題,由於同源限制的問題,我們不得不去克服這個問題,這個時候我們可以要求服務端,設定header頭,header('Access-Control-Allow-Origin: *');或者叫設定nginx配置

add_header 'Access-Control-Allow-Origin' 'http://yourweb.com';  
add_header 'Access-Control-Allow-Credentials' 'true';  
add_header 'Access-Control-Allow-Methods' 'GET';

當然這不是最好的做法,實際現在我們也可以這麼做:

ajax -> 代理 -> API

我們可以用php的curl或者通過伺服器的配置來實現反向代理。從而達到同源的效果。

前端工程師一定要要求每次請求的資料介面一嚴格遵循基礎的資料結構要求,儘管js是弱變數型別語言,但是我們還是應該嚴格要求,是陣列,就不應該是物件,是數字就不應該是字串,這樣做有利於降低隱藏bug並且提升前後端工作效率。

JSONP

JSONP算作JSON的一種”使用模式”,可用於解決主流瀏覽器的跨域資料訪問的問題。由於CORS的支援,我們可以簡單的將資料封裝成一個js指令碼請求,當然我們在jquery中會用到。

function logResults(json){  
  console.log(json);
}
$.ajax({
  url: "https://yourapi.com/api",
  dataType: "jsonp",
  jsonpCallback: "logResults"
});

comet

聊Comet我們還得說下短輪詢,由於某些特定的業務需求,比如通知,我們需要有及時的資料更新,我們能夠想到的就是使用setInterval每隔一定時間比如10s去獲取一次請求,從而做到一些通知更新,但是這並不一種高效的做法,這會增加伺服器的請求數量。這個時候有了另外一種概念,“反向Ajax”,由伺服器進行資料推送, Comet能夠讓資訊近乎實時的被推送到頁面上,非常適合要求實時性的獲取的資料的頁面。

如圖所示,就是一個簡單的Comet模型,就是資料請求後掛起,直到有資料響應推送到客戶端,這個時候客戶端再發起一個新的連線。

這樣相對來說可以減少一定數量的請求,以及資料的及時響應,從而一定意義的實現所謂推送。

一個簡單的PHP Demo程式碼,就是我們需要這端程式碼一直執行著…

while(true) {  
    set_time_limit(0);
    echo 'data';
    flush();
    b_flush();
    sleep(3);
}

JavaScript:

function createStreamingClient(url,progress,finished){
    var xhr=new XMLHttpRequest(),received=0;
    xhr.open("get",url,true);
    xhr.onreadystatechange=function(){
        var result;
        if(xhr.readyState==3){
            result=xhr.responseText.substring(received);
            received+=result.length;
            progress(result);
        }else if(xhr.readyState==4){
             finished(xhr.responseText);
        }
    };
    xhr.send(null);
    return xhr;
}

//  var client = createStreamingClient(url,fuc1,func2)

SSE Server-Sent Events

SSE是圍繞只讀Comet互動推出的API或者模式。SSE API用於建立到伺服器的單向連線,伺服器通過這個連線可以傳送任意數量的資料。伺服器響應的MIME型別必須是text/event-stream,而且是瀏覽器中的JavaScriptAPI能解析的格式輸出。

現對於Comet,我們可以看出我們只進行了一次連線,然後服務端會去控制資料的響應,從而傳送給客戶端。這樣相對來說,但是如同定義的描述,這種只適合只讀資料的情形。比如一些通知和狀態碼這樣的。SEE的使用非常簡單,只需要掌握這幾個api就行:

var es = new EventSource('http://your.api.com'  
function listener(event) {  
    console.log(event.data);
}
// 建立一個SSE連線
es.addEventListener("open", listener);  
// 響應獲取訊息的事件
es.addEventListener("message", listener);  
// 發生錯誤
es.addEventListener("error", listener);

注意:如果在回話過程中遇見錯誤後,預設程式會重新發起一次新的連線,從而防止掛掉就不再響應了

https://www.tmojm.com 創業加盟網

Web Sockets

html5 WebSocket 設計出來的目的就是要取代輪詢和 Comet技術,使客戶端瀏覽器具備像 C/S 架構下桌面系統的實時通訊能力。 瀏覽器通過 JavaScript 向伺服器發出建立 WebSocket 連線的請求,連線建立以後,客戶端和伺服器端就可以通過 TCP 連線直接交換資料。也就是我們可以使用web技術構建實時性的程式比如聊天遊戲等應用。

其實Web Sockets 的API很少,就下面這些

websocket = new WebSocket("ws://your.socket.com:9001");  
// 大開
websocket.onopen = function(evt) { /* do stuff */ }; //on open event  
// 當web socket關閉
websocket.onclose = function(evt) { /* do stuff */ };  
// 進行通訊時
websocket.onmessage = function(evt) { /* do stuff */ };  
// 發生錯誤時
websocket.onerror = function(evt) { /* do stuff */ };  
// 向伺服器發發送訊息
websocket.send(message); //send method  
websocket.close(); //close method

對於服務端的話,PHP支援了很多socket 相關api,但是我們可以使用更加成熟的框架(實用)比如phpsocket.io,Ratchet.當然node.js寫 socket也非常得心應手,node.js對高併發支援相對較好,可以使用http://socket.io/。

服務端大概會做下面的事情: + 建立一個socket + 繫結地址和埠 + 監聽進入的連線 + 接收新的連線 + web socket 握手 + 解碼資料

注意:SSE和 Web Sockets都是新的api,需要大家考慮相容性*

小結

說了那麼多簡單總結下,大家想明白幾點就行了,客戶端與服務端誰先主動,是否強調資料的實時性。

  • AJAX – 請求 → 響應 (頻繁使用)
  • Comet – 請求 → 掛起 → 響應 (模擬服務端推送)
  • Server-Sent Events – 客戶單 ← 服務端 (服務端推送)
  • WebSockets – 客戶端 ↔ 服務端 (未來趨勢,雙工通訊)