You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native中pusher-websocket-react-native的onEvent方法无响应

实时事件推送故障排查(Laravel + React Native + Laravel Websockets)

技术栈

  • 后端:Laravel,基于Laravel Websockets实现事件广播
  • 前端:React Native,通过Pusher客户端订阅广播频道

后端实现

接口处理逻辑

通过store方法处理请求,验证参数后创建Trip实例并分发EventCreated事件:

public function store(Request $request)
{
    try{
        $validator= Validator::make($request->all(), [
            'origin' => 'required',
            'originName'=>'required',
            'comments'
         ]);
         
         if($validator->fails()){
             return $validator->errors();
         }
         $trip= $request->user()->trips()->create($request->only([
            'origin',
            'originName',
            'comments',
         ]));
        EventCreated::dispatch($trip, $request->user());
        return $trip;
    } catch(\Exception $e){
        return response()->json(['error'=> $e->getMessage()], 400);
    }
}

事件定义

EventCreated事件实现ShouldBroadcast接口,指定广播到公开频道drivers:

<?php

namespace App\Events;

use App\Models\Trip;
use App\Models\User;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;

class EventCreated implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $trip;
    private $user;
    
    public function __construct(Trip $trip, User $user)
    {
        $this->trip = $trip;
        $this->user = $user;
    }

    public $queue = 'default';

    public function broadcastOn(): array
    {
        return [
            new Channel('drivers')
        ];
    }
}

React Native前端实现

触发逻辑

通过按钮点击初始化Pusher并订阅频道:

<Button title="订阅频道" onPress={getPusher} />

Pusher客户端配置

const pusher = Pusher.getInstance();

const onEvent = (event: PusherEvent)=>{
  console.log(`onEvent> ${event}`)
}

const onSubscriptionSucceeded = (channelName) => {
  console.log(channelName)
  console.log(
    `onSubscriptionSucceeded: ${channelName}`
  );
  const channel= pusher.getChannel(channelName);

  if (!channel) {
   console.log("No Channel");
   return
  }
  const me = channel.me;
  console.log(me);
}
    
const onError = (message, code, error) => {
  console.log(`onError: ${message} code: ${code} exception: ${error}`);
};

const onSubscriptionError = (
  channelName,
  message,
  e
) => {
  console.log(`onSubscriptionError: ${message}, channelName: ${channelName} e: ${e}`);
};

const onDecryptionFailure = (eventName, reason) => {
  console.log(`onDecryptionFailure: ${eventName} reason: ${reason}`);
};

const onConnectionStateChange = (
  currentState,
  previousState
) => {
  console.log(
    `onConnectionStateChange. previousState=${previousState} newState=${currentState}`
  );
};

const getPusher = async()=>{
  try{
    await pusher.init({
      apiKey: APP_KEY,
      cluster: APP_CLUSTER,
      authEndpoint: "http://127.0.0.1:8000/pusher/broadcasting/auth",
      port: 6001,
      onConnectionStateChange,
      onError,
      onEvent,
      onSubscriptionSucceeded,
      onSubscriptionError,
      onDecryptionFailure
    }).catch(error=>console.log(error));
    
    await pusher.subscribe({channelName:'drivers'});
    await pusher.connect();
    console.log(pusher)
  } catch(e){
    console.log(`ERROR> ${e}`)
  }
}

问题现象

点击按钮后成功订阅drivers频道,但通过Postman调用后端接口触发事件分发时,React Native端的onEvent方法无任何输出,未接收到事件数据。尝试将事件类改为实现ShouldBroadcastNow接口,问题仍存在。


排查与解决步骤

  1. 确认事件广播名称匹配
    Laravel事件默认广播名称为类名的蛇形格式,例如EventCreated对应事件名event_created。修改onEvent回调打印完整事件信息,确认是否监听了正确的事件名:
const onEvent = (event: PusherEvent)=>{
  console.log(`事件名: ${event.eventName}, 数据: ${JSON.stringify(event.data)}`);
}
  1. 检查Laravel Websockets服务与队列状态
  • 确保php artisan websockets:serve命令正在运行,访问Laravel Websockets控制台查看是否有事件广播记录
  • 若使用ShouldBroadcast接口,需启动队列 worker:php artisan queue:work;使用ShouldBroadcastNow则无需队列,但需确保事件未被阻塞
  1. 修正Pusher客户端网络配置
  • 真机调试时,authEndpoint和wsHost需使用电脑的局域网IP(而非127.0.0.1),否则真机无法连接到本地服务
  • 本地调试关闭SSL加密,避免证书问题:
await pusher.init({
  apiKey: APP_KEY,
  cluster: APP_CLUSTER,
  authEndpoint: "http://你的局域网IP:8000/pusher/broadcasting/auth",
  wsHost: "你的局域网IP",
  wsPort: 6001,
  encrypted: false,
  // ...其他回调
});
  1. 调整事件广播数据可见性
    事件中的$user为私有属性,不会被序列化广播。若需传递用户数据,可改为public属性或自定义广播数据:
// 方法1:改为public属性
public $user;

// 方法2:自定义广播数据
public function broadcastWith()
{
    return [
        'trip' => $this->trip,
        'user' => $this->user->only('id', 'name')
    ];
}
  1. 简化公开频道订阅配置
    drivers为公开频道,无需认证,可移除前端配置中的authEndpoint,避免不必要的认证请求干扰:
await pusher.init({
  apiKey: APP_KEY,
  cluster: APP_CLUSTER,
  wsHost: "你的局域网IP",
  wsPort: 6001,
  encrypted: false,
  // ...其他回调
});
  1. 手动测试事件广播
    通过Laravel Websockets控制台的「Message」功能,手动发送事件到drivers频道:
  • 频道名:drivers
  • 事件名:event_created
  • 数据:{"trip": {"id": 1, "origin": "测试地址"}}
    若前端能收到,说明后端事件触发逻辑有问题;若收不到,说明前端客户端配置存在故障

内容的提问来源于stack exchange,提问作者John Smith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 09:24:54