總所周知,laravel中的中間件 分爲 前置,後置,terminable中間件(也叫可終止的中間件),在官方文檔中是這樣介紹的
這樣就讓人很好奇,於是我就做了幾個測試.
新建了一箇中間件
我創建了一個全新的laravel項目,並新建了一箇中間件,並加上了 terminate 方法,這樣他就成爲了 terminate 中間件了
同時我也準備了兩種請求方法,一個是直接頁面請求blade模板,另一種是ajax請求接口形式
1 頁面請求blade模板
1.1 新建一個控制器,定義一個返回blade模板的方法
public function test_mid_blade()
{
return view('test_mid_blade');
}
1.2 新建一個模板並且打印當前時間
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
</head>
<body>
<div class="">
這是blade模板 {{ date('Y-m-d H:i:s') }}
</div>
</body>
</html>
1.3 結果和預期一樣,先返回頁面,打印當前時間,並且5秒後打下日誌
2 ajax請求接口
2.1 新建一個控制器方法,返回當前時間
public function test_mid()
{
return '服務器當前時間 '.date('Y-m-d H:i:s',time());
}
2.2 通過jsajax獲取時間,並且在console打印
<script>
console.log('發起請求時間' + getDate());
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET","http://localhost:8080/test_mid");
xmlhttp.send();
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
console.log('收到請求時間' + getDate());
console.log(xmlhttp.responseText);
}
}
function getDate(){
var myDate = new Date();
//獲取當前年
var year = myDate.getFullYear();
//獲取當前月
var month = myDate.getMonth() + 1;
//獲取當前日
var date = myDate.getDate();
var h = myDate.getHours(); //獲取當前小時數(0-23)
var m = myDate.getMinutes(); //獲取當前分鐘數(0-59)
var s = myDate.getSeconds();
//獲取當前時間
var now = year + '-' + conver(month) + "-" + conver(date) + " " + conver(h) + ':' + conver(m) + ":" + conver(s);
return now;
}
// 日期時間處理
function conver(s) {
return s < 10 ? '0' + s : s;
}
</script>
2.3 結果卻不是我們預期的,雖然js獲取的時間的確是發起請求時間,但是結果卻是在5秒後發送回來的,而在這個5秒裏,js一直處於阻塞狀態
結果表明,這個terminate中間件的確是在結果返回了瀏覽器後繼續執行,由於此時連接還沒斷開,所以對於ajax這樣的請求來說,他必須等待請求完全斷開他纔會繼續執行接下去的步驟,但是balde模板類的請求來說,這樣的確可以節省一下請求時間,來提高客戶體驗好感
接下來看laravel的代碼實現
首先我的laravel 版本是 5.8,在 根目錄/public/index.php,文件中
先看 發送到瀏覽器,這裏是用 vendor/symfony/http-foundation/Response.php 中的 send 方法
主要是通過 ob-end-flush 方法來發送數據給客戶端,然後再執行 terminate方法
使用的是 vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php 中的 terminate 方法
這樣,代碼實現完成了