国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

廣播系統(tǒng)

廣播系統(tǒng)


廣播系統(tǒng)

簡介

在現(xiàn)代的 web 應(yīng)用程序中, WebSockets 被用來實(shí)現(xiàn)實(shí)時(shí)、即時(shí)更新的用戶接口。當(dāng)服務(wù)器上的數(shù)據(jù)更新后,更新信息會(huì)通過 WebSocket 連接發(fā)送到客戶端等待處理。相比于不停地輪詢應(yīng)用程序,這是一種更加可靠和高效的選擇。

為了幫助你構(gòu)建這類應(yīng)用, Laravel 將通過 WebSocket 連接來使「廣播」 事件 變得更加輕松。 廣播 Laravel 事件允許你在服務(wù)端和客戶端 JavaScript 應(yīng)用程序間共享相同的事件名。

{注} 在深入了解事件廣播之前,請確認(rèn)你已閱讀所有關(guān)于 Laravel 事件和監(jiān)聽器 的文檔。

配置

所有關(guān)于事件廣播的配置都保存在 config/broadcasting.php 配置文件中。 Laravel 自帶了幾個(gè)廣播驅(qū)動(dòng): Pusher 、 Redis , 和一個(gè)用于本地開發(fā)與調(diào)試的 log 驅(qū)動(dòng)。另外,還有一個(gè) null 驅(qū)動(dòng)允許你完全關(guān)閉廣播系統(tǒng)。每一個(gè)驅(qū)動(dòng)的示例配置都可以在 config/broadcasting.php 配置文件中找到。

廣播服務(wù)提供者

在對(duì)事件進(jìn)行廣播之前,你必須先注冊 App\Providers\BroadcastServiceProvider 。對(duì)于一個(gè)新建的 Laravel 應(yīng)用程序,你只需要在 config/app.php 配置文件的 providers 數(shù)組中取消對(duì)該提供者的注釋即可。該提供者將允許你注冊廣播授權(quán)路由和回調(diào)。

CSRF 令牌

Laravel Echo 需要訪問當(dāng)前會(huì)話的 CSRF 令牌。你應(yīng)當(dāng)驗(yàn)證你的應(yīng)用程序的 head HTML 元素是否定義了包含 CSRF 令牌的 meta 標(biāo)簽:

<meta name="csrf-token" content="{{ csrf_token() }}">

對(duì)驅(qū)動(dòng)的要求

Pusher

如果你使用 Pusher 來對(duì)事件進(jìn)行廣播,請用 Composer 包管理器來安裝 Pusher PHP SDK :

composer require pusher/pusher-php-server "~3.0"

然后,你需要在 config/broadcasting.php 配置文件中配置你的 Pusher 證書。該文件中已經(jīng)包含了一個(gè) Pusher 示例配置,你可以快速地指定你的 Pusher key 、secret 和 application ID。 config/broadcasting.php 文件的 pusher 配置項(xiàng)同時(shí)也允許你指定 Pusher 支持的額外 options ,例如 cluster:

'options' => [ 
   'cluster' => 'eu',    
   'encrypted' => true
 ],

當(dāng) Pusher 和 Laravel Echo 一起使用時(shí),你應(yīng)該在 resources/assets/js/bootstrap.js 文件中實(shí)例化 Echo 對(duì)象時(shí)指定 pusher 作為所需要的 broadcaster :

import Echo from "laravel-echo"window.Pusher = require('pusher-js');
window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-key'
 });

Redis

如果你使用 Redis 廣播器,請安裝 Predis 庫:

composer require predis/predis

Redis 廣播器會(huì)使用 Redis 的 發(fā)布 / 訂閱 特性來廣播消息;盡管如此,你仍需將它與能夠從 Redis 接收消息的 WebSocket 服務(wù)器配對(duì)使用以便將消息廣播到你的 WebSocket 頻道上去。

當(dāng) Redis 廣播器發(fā)布一個(gè)事件的時(shí)候,該事件會(huì)被發(fā)布到它指定的頻道上去,傳輸?shù)臄?shù)據(jù)是一個(gè)采用 JSON 編碼的字符串。該字符串包含了事件名、 data 數(shù)據(jù)和生成該事件 socket ID 的用戶(如果可用的話)。

Socket.IO

如果你想將 Redis 廣播器 和 Socket.IO 服務(wù)器進(jìn)行配對(duì),你需要在你的應(yīng)用程序中引入 Socket.IO JavaScript 客戶端庫。你可以通過 NPM 包管理器進(jìn)行安裝:

npm install --save socket.io-client

然后,你需要在實(shí)例化 Echo 時(shí)指定 socket.io 連接器和 host 。

import Echo from "laravel-echo"window.io = require('socket.io-client');
window.Echo = new Echo({
    broadcaster: 'socket.io',
    host: window.location.hostname + ':6001'
 });

最后,你需要運(yùn)行一個(gè)與 Laravel 兼容的 Socket.IO 服務(wù)器。 Laravel 官方并沒有內(nèi)置 Socket.IO 服務(wù)器實(shí)現(xiàn);不過,可以選擇一個(gè)由社區(qū)驅(qū)動(dòng)維護(hù)的項(xiàng)目 tlaverdure/laravel-echo-server ,目前托管在 GitHub 。

對(duì)隊(duì)列的要求

在開始廣播事件之前,你還需要配置和運(yùn)行 隊(duì)列監(jiān)聽器 。所有的事件廣播都是通過隊(duì)列任務(wù)來完成的,因此應(yīng)用程序的響應(yīng)時(shí)間不會(huì)受到明顯影響。

概念綜述

Laravel 的事件廣播允許你使用基于驅(qū)動(dòng)的 WebSockets 將服務(wù)端的 Laravel 事件廣播到客戶端的 JavaScript 應(yīng)用程序。當(dāng)前的 Laravel 自帶了 Pusher 和 Redis 驅(qū)動(dòng)。通過使用 Laravel Echo 的 Javascript 包,我們可以很方便地在客戶端消費(fèi)事件。

事件通過「頻道」來廣播,這些頻道可以被指定為公開或私有的。任何訪客都可以不經(jīng)授權(quán)或認(rèn)證訂閱一個(gè)公開頻道;然而,如果想要訂閱一個(gè)私有頻道,那么該用戶必須通過認(rèn)證,并獲得該頻道的授權(quán)。

使用示例程序

在深入了解事件廣播的每個(gè)組件之前,讓我們先用一個(gè)電子商務(wù)網(wǎng)站作為例子來概覽一下。我們不會(huì)討論配置 Pusher 或者 Laravel Echo 的細(xì)節(jié),這些會(huì)在本文檔的其它章節(jié)里詳細(xì)討論。

在我們的應(yīng)用程序中,我們假設(shè)有一個(gè)允許用戶查看訂單配送狀態(tài)的頁面。有一個(gè) ShippingStatusUpdated 事件會(huì)在配送狀態(tài)更新時(shí)被觸發(fā):

event(new ShippingStatusUpdated($update));

ShouldBroadcast 接口

當(dāng)用戶在查看自己的訂單時(shí),我們不希望他們必須通過刷新頁面才能看到狀態(tài)更新。我們希望一旦有更新時(shí)就主動(dòng)將更新信息廣播到客戶端。所以,我們必須標(biāo)記 ShippingStatusUpdated 事件實(shí)現(xiàn) ShouldBroadcast 接口。這會(huì)讓 Laravel 在事件被觸發(fā)時(shí)廣播該事件:

<?php
   namespace App\Events;
   use Illuminate\Broadcasting\Channel;
   use Illuminate\Queue\SerializesModels;
   use Illuminate\Broadcasting\PrivateChannel;
   use Illuminate\Broadcasting\PresenceChannel;
   use Illuminate\Broadcasting\InteractsWithSockets;
   use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
   class ShippingStatusUpdated implements ShouldBroadcast{  
     /**
     * 有關(guān)配送狀態(tài)更新的信息。
     *
     * @var string
     */  
   public $update;
  }

ShouldBroadcast 接口要求事件定義一個(gè) broadcastOn 方法。該方法負(fù)責(zé)指定事件被廣播到哪些頻道。在(通過 Artisan 命令)生成的事件類中,一個(gè)空的 broadcastOn 方法已經(jīng)被預(yù)定義好了,所以我們只需要完成其細(xì)節(jié)即可。我們希望只有訂單的創(chuàng)建者能夠看到狀態(tài)的更新,所以我們要把該事件廣播到與這個(gè)訂單綁定的私有頻道上去:

/**
 * 獲取事件應(yīng)該廣播的頻道。
 *
 * @return array
 */
 public function broadcastOn(){ 
    return new PrivateChannel('order.'.$this->update->order_id);
 }

授權(quán)頻道

記住,用戶只有在被授權(quán)之后才能監(jiān)聽私有頻道。我們可以在 routes/channels.php 文件中定義頻道的授權(quán)規(guī)則。在本例中,我們需要對(duì)視圖監(jiān)聽私有 order.1 頻道的所有用戶進(jìn)行驗(yàn)證,確保只有訂單真正的創(chuàng)建者才能監(jiān)聽:

Broadcast::channel('order.{orderId}', function ($user, $orderId) { 
   return $user->id === Order::findOrNew($orderId)->user_id;
});

channel 方法接收兩個(gè)參數(shù):頻道名稱和一個(gè)回調(diào)函數(shù),該回調(diào)通過返回 true 或者 false 來表示用戶是否被授權(quán)監(jiān)聽該頻道。

所有的授權(quán)回調(diào)接收當(dāng)前被認(rèn)證的用戶作為第一個(gè)參數(shù),任何額外的通配符參數(shù)作為后續(xù)參數(shù)。在本例中,我們使用 {orderId} 占位符來表示頻道名稱的 「ID」 部分是通配符。

對(duì)事件廣播進(jìn)行監(jiān)聽

接下來,就只剩下在 JavaScript 應(yīng)用程序中監(jiān)聽事件了。我們可以通過 Laravel Echo 來實(shí)現(xiàn)。首先,我們使用 private 方法來訂閱私有頻道。然后,使用 listen 方法來監(jiān)聽 ShippingStatusUpdated 事件。默認(rèn)情況下,事件的所有公有屬性會(huì)被包括在廣播事件中:

Echo.private(`order.${orderId}`)
    .listen('ShippingStatusUpdated', (e) => {
        console.log(e.update);  
      });

定義廣播事件

要告知 Laravel 一個(gè)給定的事件需要廣播,只需要在事件類中實(shí)現(xiàn) Illuminate\Contracts\Broadcasting\ShouldBroadcast 接口即可。該接口已被導(dǎo)入到所有由框架生成的事件類中,所以你可以很方便地將它添加到你自己的事件中。

ShouldBroadcast 接口要求你實(shí)現(xiàn)一個(gè)方法: broadcastOn 。 該方法返回一個(gè)頻道或者一個(gè)頻道數(shù)組,事件會(huì)被廣播到這些頻道。這些頻道必須是 Channel 、PrivateChannel 或者 PresenceChannel 的實(shí)例。 Channel 代表任何用戶都可以訂閱的公開頻道, 而 PrivateChannelsPresenceChannels 則代表需要 頻道授權(quán) 的私有頻道:

<?php
    namespace App\Events;
    use Illuminate\Broadcasting\Channel;
    use Illuminate\Queue\SerializesModels;
    use Illuminate\Broadcasting\PrivateChannel;
    use Illuminate\Broadcasting\PresenceChannel;
    use Illuminate\Broadcasting\InteractsWithSockets;
    use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
    class ServerCreated implements ShouldBroadcast{ 
       use SerializesModels;    
       public $user;  
     /**
     * 創(chuàng)建一個(gè)新的事件實(shí)例。
     *
     * @return void
     */ 
      public function __construct(User $user) 
         {      
             $this->user = $user; 
         }   
      /**
     *獲得事件廣播的頻道。
     *
     * @return Channel|array
     */   
   public function broadcastOn()  
     {     
        return new PrivateChannel('user.'.$this->user->id);   
      }
 }

然后,你只需要像你平時(shí)那樣 觸發(fā)事件 。一旦事件被觸發(fā),一個(gè) 隊(duì)列任務(wù) 會(huì)自動(dòng)廣播事件到你指定的廣播驅(qū)動(dòng)上。

廣播名稱

Laravel 默認(rèn)會(huì)使用事件的類名作為廣播名稱來廣播事件。不過,你也可以在事件類中定義一個(gè) broadcastAs 方法來自定義廣播名稱:

/**
 * 事件的廣播名稱。
 *
 * @return string
 */
 public function broadcastAs(){
     return 'server.created';
  }

如果你使用了 broadcastAs 方法來自定義廣播名稱,你應(yīng)當(dāng)確保在你注冊監(jiān)聽器時(shí)加上一個(gè) . 的前綴。這將指示 Echo 不要在事件之前添加應(yīng)用程序的命名空間:

.listen('.server.created', function (e) {
    ....
});

廣播數(shù)據(jù)

當(dāng)一個(gè)事件被廣播時(shí),其所有的 public 屬性都會(huì)自動(dòng)序列化并作為事件有效載荷進(jìn)行廣播,這允許你在 JavaScript 應(yīng)用程序中訪問到事件所有的公有數(shù)據(jù)。舉個(gè)例子,如果你的事件有一個(gè)單獨(dú)的包含了一個(gè) Eloquent 模型的公有 $user 屬性,那么事件的廣播有效載荷將會(huì)是:

{ 
   "user": {
       "id": 1,       
       "name": "Patrick Stewart"  
      ...  
      }
 }

不過,如果你想更細(xì)粒度地控制你的廣播有效載荷,你可以向你的事件中添加一個(gè) broadcastWith 方法。這個(gè)方法會(huì)返回一個(gè)你想要作為事件有效載荷進(jìn)行廣播的數(shù)據(jù)數(shù)組:

/**
 * 指定廣播數(shù)據(jù)。
 *
 * @return array
 */
 public function broadcastWith(){
     return ['id' => $this->user->id];
 }

廣播隊(duì)列

默認(rèn)情況下,每一個(gè)廣播事件都會(huì)被推送到在 queue.php 配置文件中指定的默認(rèn)隊(duì)列連接相應(yīng)的默認(rèn)隊(duì)列中。你可以在事件類中定義一個(gè) broadcastQueue 屬性來自定義廣播器所使用的隊(duì)列。該屬性需要你指定廣播時(shí)你想要用的隊(duì)列名稱:

/**
 * 事件被推送到的隊(duì)列名稱。
 *
 * @var string
 */
 public $broadcastQueue = 'your-queue-name';

如果你想使用 sync 隊(duì)列而不是默認(rèn)隊(duì)列驅(qū)動(dòng)來廣播事件,你可以實(shí)現(xiàn) ShouldBroadcastNow 接口而不是 ShouldBroadcast

<?php
  use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
  class ShippingStatusUpdated implements ShouldBroadcastNow{ 
     //
  }

廣播條件

有時(shí),你想在給定條件為 true 的情況下才廣播你的事件。你可以通過在事件類中添加一個(gè) broadcastWhen 方法來定義這些條件:

/**
 * 判定事件是否可以廣播。
 *
 * @return bool
 */
 public function broadcastWhen(){ 
    return $this->value > 100;
 }

授權(quán)頻道

對(duì)于私有頻道,用戶只有被授權(quán)之后才能監(jiān)聽。實(shí)現(xiàn)過程是用戶向你的 Laravel 應(yīng)用程序發(fā)起一個(gè)攜帶頻道名稱的 HTTP 請求,由你的應(yīng)用程序判斷該用戶是否能夠監(jiān)聽該頻道。在使用 Laravel Echo 時(shí),授權(quán)訂閱私有頻道的 HTTP 請求會(huì)自動(dòng)發(fā)送;盡管如此,你仍需定義相應(yīng)的路由來響應(yīng)這些請求。

定義授權(quán)路由

幸運(yùn)的是,在 Laravel 中我們可以很容易地定義路由來響應(yīng)頻道授權(quán)請求。在 Laravel 自帶的 BroadcastServiceProvider 中,你可以看到對(duì) Broadcast::routes 方法的調(diào)用。該方法會(huì)注冊 /broadcasting/auth 路由來處理授權(quán)請求:

Broadcast::routes();

Broadcast::routes 方法會(huì)自動(dòng)將它的路由置入 web 中間件組中;不過,如果你想自定義指定的屬性,你可以向該方法傳遞一個(gè)路由屬性數(shù)組:

Broadcast::routes($attributes);

自定義授權(quán)端點(diǎn)

默認(rèn)情況下,Echo 將使用 /broadcasting/auth 端點(diǎn)來授權(quán)頻道訪問。 但是,您可以通過將 authEndpoint 配置選項(xiàng)傳遞給 Echo 實(shí)例來指定自己的授權(quán)端點(diǎn):

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-key',
    authEndpoint: '/custom/endpoint/auth'
 });

定義授權(quán)回調(diào)

接下來,我們需要定義真正用于處理頻道授權(quán)的邏輯。該邏輯在應(yīng)用程序自帶的 routes/channels.php 文件中完成。在這個(gè)文件中,你可以使用 Broadcast::channel 方法來注冊頻道授權(quán)回調(diào):

Broadcast::channel('order.{orderId}', function ($user, $orderId) { 
   return $user->id === Order::findOrNew($orderId)->user_id;
});

channel 方法接收兩個(gè)參數(shù):頻道名稱和一個(gè)回調(diào)函數(shù),該回調(diào)通過返回 true 或者 false 來表示用戶是否被授權(quán)監(jiān)聽該頻道。

所有的授權(quán)回調(diào)接收當(dāng)前認(rèn)證用戶作為第一個(gè)參數(shù),任何額外的通配符參數(shù)作為后續(xù)參數(shù)。在本例中,我們使用 {orderId} 占位符來表示頻道名稱的 「ID」 部分是通配符。

授權(quán)回調(diào)模型綁定

就像 HTTP 路由一樣,頻道路由也可以利用顯式或隱式 路由模型綁定 。例如,你可以請求接收一個(gè)真正的 Order 模型實(shí)例,而不是字符串或數(shù)字類型的 order ID:

use App\Order;
Broadcast::channel('order.{order}', function ($user, Order $order) { 
   return $user->id === $order->user_id;
 });

授權(quán)回調(diào)驗(yàn)證

私有頻道和在線廣播頻道通過應(yīng)用程序的默認(rèn)授權(quán)驗(yàn)證對(duì)當(dāng)前用戶身份進(jìn)行驗(yàn)證。 如果用戶未經(jīng)過授權(quán)驗(yàn)證,則會(huì)自動(dòng)拒絕通道授權(quán),并且永遠(yuǎn)不會(huì)執(zhí)行授權(quán)回調(diào)。 但是,您可以分配多個(gè)自定義防護(hù),以便在必要時(shí)對(duì)傳入請求進(jìn)行身份驗(yàn)證:

 Broadcast::channel('channel', function() { 
    // ...
  }, ['guards' => ['web', 'admin']])

定義頻道類

如果你的應(yīng)用程序用到了許多不同的頻道,你的 routes/channels.php 文件可能會(huì)變得很龐大。所以,你可以使用頻道類來代替使用閉包授權(quán)頻道。要生成一個(gè)頻道類,請使用 make:channel Artisan 命令。該命令會(huì)在 App/Broadcasting 目錄中放置一個(gè)新的頻道類。

php artisan make:channel OrderChannel

接下來,在你的 routes/channels.php 文件中注冊你的頻道:

use App\Broadcasting\OrderChannel;
Broadcast::channel('order.{order}', OrderChannel::class);

最后,你可以將頻道的授權(quán)邏輯放入頻道類的 join 方法中。該 join 方法將保存你通常放置在頻道授權(quán)閉包中的相同邏輯。當(dāng)然,你也可以利用頻道模型綁定:

<?php
    namespace App\Broadcasting;
    use App\User;use App\Order;
    class OrderChannel{   
     /**
     * 創(chuàng)建一個(gè)新的頻道實(shí)例。
     *
     * @return void
     */ 
     public function __construct()  
       {     
          //  
        }   
     /**
     * 認(rèn)證用戶的頻道訪問權(quán)限。
     *
     * @param  \App\User  $user
     * @param  \App\Order  $order
     * @return array|bool
     */    
    public function join(User $user, Order $order) 
       {     
          return $user->id === $order->user_id;  
        }
   }

{注} 就像 Laravel 中的很多其它類,頻道類會(huì)通過 服務(wù)容器 自動(dòng)解析。因此,你可以在頻道類的構(gòu)造函數(shù)中對(duì)其進(jìn)行所需依賴項(xiàng)的類型提示。

廣播事件

定義好一個(gè)事件且將其標(biāo)記實(shí)現(xiàn) ShouldBroadcast 接口之后,你所要做的僅僅是通過 event 函數(shù)來觸發(fā)該事件。事件分發(fā)器會(huì)識(shí)別出標(biāo)記了實(shí)現(xiàn) ShouldBroadcast 接口的事件,并將其推送到隊(duì)列中進(jìn)行廣播:

event(new ShippingStatusUpdated($update));

只廣播給他人

當(dāng)創(chuàng)建一個(gè)會(huì)用到事件廣播的應(yīng)用程序時(shí),你可以使用 broadcast 函數(shù)來代替 event 。和 event 函數(shù)一樣, broadcast 函數(shù)將事件分發(fā)到服務(wù)端監(jiān)聽器:

broadcast(new ShippingStatusUpdated($update));

不過, broadcast 函數(shù)還有一個(gè)允許你將當(dāng)前用戶排除在廣播接收者之外的 toOthers 方法:

broadcast(new ShippingStatusUpdated($update))->toOthers();

為了更好地理解什么時(shí)候使用 toOthers 方法,讓我們假設(shè)有一個(gè)任務(wù)列表的應(yīng)用程序,用戶可以通過輸入任務(wù)名來新建任務(wù)。要新建任務(wù),你的應(yīng)用程序需要發(fā)起一個(gè)請求到一個(gè) /task 路由,該路由會(huì)廣播任務(wù)的創(chuàng)建,并返回新任務(wù)的 JSON 響應(yīng)。當(dāng)你的 JavaScript 應(yīng)用程序從路由收到響應(yīng)后,它會(huì)直接將新任務(wù)插入到任務(wù)列表中,就像這樣:

axios.post('/task', task) 
   .then((response) => {
        this.tasks.push(respo   
      });

然而,別忘了,我們還廣播了任務(wù)的創(chuàng)建。如果你的 JavaScript 應(yīng)用程序正在監(jiān)聽該事件以便添加任務(wù)至任務(wù)列表,任務(wù)列表中將出現(xiàn)重復(fù)的任務(wù):一個(gè)來自路由響應(yīng),另一個(gè)來自廣播。你可以通過使用 toOthers 方法告知廣播器不要將事件廣播到當(dāng)前用戶來解決這個(gè)問題。

{注} 為了能調(diào)用 toOthers 方法,你的事件必須使用 Illuminate\Broadcasting\InteractsWithSockets trait 。

配置

當(dāng)你初始化 Laravel Echo 實(shí)例的時(shí)候,一個(gè)套接字 ID 會(huì)被分配到該連接。如果你使用了 VueAxios ,該套接字 ID 會(huì)自動(dòng)地以 X-Socket-ID 頭的方式添加到每一個(gè)傳出請求中。那么,當(dāng)你調(diào)用 toOthers 方法時(shí),Laravel 會(huì)從請求頭中取出套接字 ID ,并告知廣播器不要廣播任何消息到帶有這個(gè)套接字 ID 的連接上。

你如果你沒有使用 Vue 和 Axios ,則需要手動(dòng)配置 JavaScript 應(yīng)用程序來發(fā)送 X-Socket-ID 請求頭。你可以用 Echo.socketId 方法來獲取套接字 ID :

var socketId = Echo.socketId();

接收廣播

安裝 Laravel Echo

Laravel Echo 是一個(gè) JavaScript 庫,有了這個(gè)庫之后,訂閱頻道監(jiān)聽 Laravel 廣播的事件變得非常容易。你可以通過 NPM 包管理器來安裝 Echo 。在本例中,因?yàn)槲覀儠?huì)使用 Pusher 廣播器,所以我們也會(huì)安裝 pusher-js 包:

npm install --save laravel-echo pusher-js

安裝好 Echo 之后,你就可以在應(yīng)用程序的 JavaScript 中創(chuàng)建一個(gè)全新的 Echo 實(shí)例。做這件事的一個(gè)理想的地方是在 Laravel 框架自帶的 resources/js/bootstrap.js 文件的底部:

import Echo from "laravel-echo"
window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-key'
  });

當(dāng)你使用 pusher 連接器來創(chuàng)建一個(gè) Echo 實(shí)例的時(shí)候,還可以指定 cluster 以及連接是否需要加密:

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-key',
    cluster: 'eu',
    encrypted: true
 });

使用現(xiàn)有客戶端實(shí)例

如果您已經(jīng)有一個(gè)希望 Echo 使用的 Pusher 或 Socket.io 客戶端實(shí)例,您可以通過 client 配置選項(xiàng)將其傳遞給 Echo:

const client = require('pusher-js');
window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-key',
    client: client
 });

對(duì)事件進(jìn)行監(jiān)聽

安裝并實(shí)例化 Echo 之后, 你就可以開始監(jiān)聽事件廣播了。首先,使用 channel 方法獲取一個(gè)頻道實(shí)例,然后調(diào)用 listen 方法來監(jiān)聽指定的事件:

Echo.channel('orders') 
   .listen('OrderShipped', (e) => {
        console.log(e.order.name);  
   });

如果你想監(jiān)聽私有頻道上的事件,請使用 private 方法。你可以通過鏈?zhǔn)秸{(diào)用 listen 方法來監(jiān)聽單個(gè)頻道上的多個(gè)事件:

Echo.private('orders') 
   .listen(...)    
   .listen(...)    
   .listen(...);

退出頻道

要離開頻道,您可以在 Echo 實(shí)例上調(diào)用 leaveChannel 方法:

Echo.leaveChannel('orders');

如果您想離開私有頻道和在線頻道,您可以調(diào)用 leave 方法:

Echo.leave('orders');

命名空間

你可能已經(jīng)注意到在上面的例子中,我們并沒有為事件類指定完整的命名空間。這是因?yàn)?Echo 會(huì)默認(rèn)事件都在 App\Events 命名空間下。不過,你可以在實(shí)例化 Echo 時(shí)傳遞一個(gè) namespace 配置項(xiàng)來指定根命名空間:

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-key',    
    namespace: 'App.Other.Namespace'
 });

另外,你可以在使用 Echo 訂閱事件的時(shí)候?yàn)槭录惣由?. 前綴。這樣就可以指定完全限定名稱的類名了:

Echo.channel('orders') 
   .listen('.Namespace.Event.Class', (e) => {     
      //  
    });

Presence 頻道

Presence 頻道構(gòu)建在私有頻道的安全性基礎(chǔ)之上,并提供了額外的特性:獲知誰訂閱了該頻道。這一點(diǎn)使構(gòu)建強(qiáng)大的,協(xié)同的應(yīng)用變得非常容易,比如一個(gè)用戶在瀏覽頁面時(shí),通知其他正在瀏覽相同頁面的用戶。

授權(quán) Presence 頻道

所有的 presence 頻道也是私有頻道;因此,用戶必須被 授權(quán)之后才能訪問 。不過,在給 presence 頻道定義授權(quán)回調(diào)函數(shù)時(shí),如果一個(gè)用戶已經(jīng)加入了該頻道,那么不應(yīng)該返回 true ,而應(yīng)該返回一個(gè)關(guān)于該用戶信息的數(shù)組。

由授權(quán)回調(diào)函數(shù)返回的數(shù)據(jù)能夠在你的 JavaScript 應(yīng)用程序中被 presence 頻道事件監(jiān)聽器所使用。如果用戶沒有被授權(quán)加入該 presence 頻道,那么你應(yīng)該返回 false 或者 null

Broadcast::channel('chat.{roomId}', function ($user, $roomId) { 
   if ($user->canJoinRoom($roomId)) {      
     return ['id' => $user->id, 'name' => $user->name];  
     }
   });

加入 Presence 頻道

你可以使用 Echo 的 join 方法來加入 presence 頻道。 join 方法會(huì)返回一個(gè)實(shí)現(xiàn)了 PresenceChannel 的對(duì)象,通過暴露 listen 方法,允許你訂閱 herejoiningleaving 事件。

Echo.join(`chat.${roomId}`) 
   .here((users) => {    
       //  
     })    
   .joining((user) => {
        console.log(user.name);   
        }) 
    .leaving((user) => {
        console.log(user.name); 
       });

here 回調(diào)函數(shù)會(huì)在你成功加入頻道后被立即執(zhí)行,并接收一個(gè)包含其他所有當(dāng)前訂閱該頻道的用戶的用戶信息數(shù)組 。 joining 方法會(huì)在新用戶加入頻道時(shí)被執(zhí)行,而 leaving 方法會(huì)在用戶退出頻道時(shí)被執(zhí)行。

廣播到 Presence 頻道

Presence 頻道可以像公開和私有頻道一樣接收事件。使用一個(gè)聊天室的例子,我們可能想把 NewMessage 事件廣播到聊天室的 presence 頻道。要實(shí)現(xiàn)它,我們將從事件的 broadcastOn 方法中返回一個(gè) PresenceChannel 實(shí)例:

/**
 * 獲得事件廣播的頻道。
 *
 * @return Channel|array
 */
 public function broadcastOn(){
     return new PresenceChannel('room.'.$this->message->room_id);
   }

就像公開或私有事件, presence 頻道事件也可以使用 broadcast 函數(shù)來廣播。同樣的,你也可以使用 toOthers 方法將當(dāng)前用戶排除在廣播接收者之外:

broadcast(new NewMessage($message));
broadcast(new NewMessage($message))->toOthers();

你可以通過 Echo 的 listen 方法來監(jiān)聽 join 事件:

Echo.join(`chat.${roomId}`) 
   .here(...)    
   .joining(...)    
   .leaving(...)    
   .listen('NewMessage', (e) => {  
         //   
     });

客戶端事件

{注} 使用 Pusher 時(shí),如果要發(fā)送客戶端事件,你必須在 應(yīng)用后臺(tái) 的「應(yīng)用設(shè)置」部分啟用「客戶端事件」選項(xiàng)。

有時(shí),你可能希望廣播一個(gè)事件給其它已經(jīng)連接的客戶端,但不通知你的 Laravel 應(yīng)用程序。這在處理「輸入中」這類事情的通知時(shí)尤其有用,比如提醒你應(yīng)用的用戶,另一個(gè)用戶正在給定屏幕上輸入信息。

你可以使用 Echo 的 whisper 方法來廣播客戶端事件:

Echo.private('chat') 
   .whisper('typing', {
        name: this.user.name    
    });

你可以使用 listenForWhisper 方法來監(jiān)聽客戶端事件:

Echo.private('chat')
    .listenForWhisper('typing', (e) => {
        console.log(e.name); 
     });

消息通知

通過與將事件廣播與 消息通知 配對(duì),你的 JavaScript 應(yīng)用程序可以在不刷新頁面的情況下接收新的消息通知。在此之前,請確保你已經(jīng)讀過了如何使用 廣播通知頻道 的文檔。

配置好使用廣播頻道的消息通知后,你可以使用 Echo 的 notification 方法來監(jiān)聽廣播事件。謹(jǐn)記,頻道名稱應(yīng)該和接收消息通知的實(shí)體類名相匹配:

Echo.private(`App.User.${userId}`) 
   .notification((notification) => {
        console.log(notification.type); 
      });

在本例中,所有通過 broadcast 頻道發(fā)送到 App\User 實(shí)例的消息通知都會(huì)被回調(diào)接收。一個(gè)針對(duì) App.User.{id} 頻道的授權(quán)回調(diào)函數(shù)已經(jīng)包含在 Laravel 框架內(nèi)置的 BroadcastServiceProvider 中了。

本文章首發(fā)在 LearnKu.com 網(wǎng)站上。