php laravel terminate中間件 實現原理與實例

總所周知,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 方法

 

這樣,代碼實現完成了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章