Aurelia 用 signalR 激活

Aurelia activate with signalR

如何将 signalR 与 aurelia canActivate() 和 activate() 页面循环一起使用? 我的意思是...在我的 VM 构造函数中,我初始化了 signalR 连接。在 canActivate() 或 activate() 方法中,我启动了 signalR 连接。在服务器端,在集线器中,当客户端连接时,我获取客户端的数据并将其发布到连接的客户端。所以Aurelia客户端会异步获取数据。所以页面会显示为空,数据来了会刷新。但是我想在显示页面之前等待来自 signalR hub 的数据。

所以工作流程是这样的:

  1. VM 构造函数 => 使用(HubConnectionBuilder)构建 signalR 连接
  2. VM Constructor => 设置连接事件,如 "onConnected"
  3. VM activate() => 通过调用 this.connection.start();
  4. 开始连接
  5. SignalR Hub.OnConnectedAsync() => 从数据库中获取数据
  6. SignalR Hub.OnConnectedAsync() => 仅将数据发送到新连接的客户端 ( Clients.Client(Context.ConnectionId).SendAsync("onConnected", data);)
  7. VM onConnected 事件处理程序 => 获取数据并设置模型 (this.model=data)

当工作流进行到第 4 步时,页面已经显示为空。

VM

@autoinject
export class AlarmsVM {
  model: any;    
  connection: HubConnection;

  constructor() {
     this.connection = new HubConnectionBuilder()
        .withUrl("/alarmsHub")
        .configureLogging(LogLevel.Information)
        .build();

    this.connection.on("onConnected", (data) => this.model = data);
    this.connection.on("onUpdate", (data) => this.model = data);
  }

  async activate() {
    await this.connection.start().catch(err => console.error(err.toString()));
  }

  async deactivate() {
    await this.connection.stop();
  }
}

signalR 集线器

public class AlarmsHub:Hub
{
    private readonly IMediator _mediator;

    public AlarmsHub(IMediator mediator)
    {
        _mediator = mediator;
    }

    public override async Task OnConnectedAsync()
    {
        var data = await _mediator.Send(new GetAlarmsQuery());
        await Clients.Client(Context.ConnectionId).SendAsync("onConnected", data);
    }

    ...
}

根据文档,您可以 return 来自 activate() 的承诺,导航只会在承诺解决时发生: https://aurelia.io/docs/api/router/interface/RoutableComponentActivate/method/activate/

编辑

我误读了你原来的问题,你基本上希望激活在收到 onConnected 事件时解决。 将 onConnected 的分辨率包装在 activate() 的 promise 中,你应该可以开始了,示例代码:

  activate() {
    this.connection.start().catch(err => console.error(err.toString()));
    return new Promise((resolve, reject) => {
       this.connection.on("onConnected", (data) => {
          this.model = data;
          return resolve();
       });
    });
  }