javascript - 是否可以在 Web Worker 中创建 signalR 流连接

标签 javascript angular signalr web-worker

我正在使用 Angular 8 和 singalR 从服务器进行图像流传输。

我注意到流媒体会减慢我的 UI 渲染速度。 我希望整个流媒体部分转移到 Web Worker,并且仅将有值(value)的内容从 Web Worker 发送到 UI 部分。

我没有代码示例,因为我不确定我的想法是否可行。
任何人都可以给我一些提示或发帖,因为我在其中没有找到任何有关 Web Worker 和 Web 套接字(signalR)连接的信息。

最佳答案

经过一番研究,我终于完成了这个。 这是可能的,并且有一些提示:

  1. https://angular.io/guide/web-worker 创建 Web Worker,ng 生成 webWorker 是该命令,Angular 将为您设置环境。 如果您在没有此命令的情况下执行此操作,则需要执行其他工作。请检查文档。

  2. 安装@microsoft/signalr 库,而不是@aspnet/signalr。我在 Web Worker 中与 @aspnet/signalr 建立连接时遇到问题。

  3. 然后从我的组件中调用工作人员来建立连接:

public establishConnectionToStreamingHub() {
  if (!this.streamingWorker) {
    this.streamingWorker = new Worker('./streaming-data.worker', { type: 'module' });

    this.streamingWorker.postMessage(<StreamingWorkerRequest>{
      action: StreamingWorkerAction.EstablishConnection,
      baseHref: this.href
    });

    this.streamingWorker.onmessage = this.onWorkerMessage;
  }
}

// listen for streaming response from worker. 
// I created interface here for message type. 
// If message is success I notified listener about it, if message is error handling should be added here.

private onWorkerMessage = (message) => {
  const response = message.data as StreamingWorkerResponse;
  if (response.type === ResponseMessageType.StreamingSuccessResult) {
    this.streamingDataNotify(response.data);
  }
}

这是我的流工作文件。 这里的要点是我有一个用于连接和流传输的类。 第一次向工作人员收到消息时,我检查消息类型是否为“StreamingWorkerAction.EstablishConnection”。 如果是,我创建新的类实例并在类构造函数中建立与集线器的连接。我也将 worker 实例发送到类(class)。 它对之后的所有流请求类对象负责。

import { StreamingWorkerAction,
  StreamingWorkerRequest,
  StreamingWorkerResponse,
  ResponseMessageType
} from './streaming-worker.model';

export class StreamingClass {
  private hubConnection: HubConnection;

  private workerInstance;
  private href = '';

  private streamingSubscription: ISubscription<Data>;


  constructor(data: StreamingWorkerRequest) {
    this.href = data.baseHref;
    this.workerInstance = data.workerInstance;

    this.connectHub().subscribe(result => {
      console.log('Streaming connection established.')
    }, error => {
      this.workerInstance.postMessage(<StreamingWorkerResponse>{
        type: ResponseMessageType.ConnectingError,
        error: error
      });
    });

    this.workerInstance.onmessage = (event) => {
      const requestData = event.data as StreamingWorkerRequest;
      if (requestData.action === StreamingWorkerAction.StartStreaming) {
        this.clearCurrentSubscription();
        this.streamingSubscription = this.startStreaming(streamingId);
      }
    };
  }

  private clearCurrentSubscription() {
    if (this.streamingSubscription) {
      this.streamingSubscription.dispose();
    }
  }

  private startStreaming(streamingId: string): ISubscription<StreamingData> {
    return this.hubConnection.stream<StreamingData>('Stream', streamingId).subscribe({
      next: data => {
        this.workerInstance.postMessage(<StreamingWorkerResponse>{
          type: ResponseMessageType.StreamingSuccessResult,
          data: data
        });
      },
      complete: () => {
        console.log('complete');
      },
      error: error => {
        this.workerInstance.postMessage(<StreamingWorkerResponse>{
          type: ResponseMessageType.StreamingError,
          error: error
        });
      }
    });
  }

  private connectHub(): Observable<boolean> {
    this.hubConnection = new HubConnectionBuilder()
       .withUrl(this.href + '/api/hub/pathToTheHub')
       .withAutomaticReconnect()
       .build();
  }

}

// web worker event listener
addEventListener('message', event => {
  const requestData = event.data as StreamingWorkerRequest;

  if (requestData.action === StreamingWorkerAction.EstablishConnection) {
    requestData.workerInstance = self;
    const streamingClass = new StreamingClass(requestData);
  }
});

更新:2020 年 2 月 9 日

在 @microsoft/signalr 库的 npm 站点上:https://www.npmjs.com/package/@microsoft/signalr

我注意到了这一点:

To use the client in a webworker, copy *.js files from the dist/webworker > >folder to your script folder include on your webworker using the importScripts >function. Note that webworker SignalR hub connection supports only absolute path >to a SignalR hub.

之后我在节点模块中找到了 webworker 文件夹:\node_modules@microsoft\signalr\dist\webworker

并将文件 signalr.js 复制到路径上的 Assets 文件夹:assets/scripts/signalr.js。

然后在我的工作文件中我导入了如下脚本:

import * as signalR from '../../../../assets/scripts/signalr.js';

并在工作文件中将所有旧的 signalR 导入从 webworker 脚本替换为新的。 例如这些行:

private hubConnection: HubConnection;  
private streamingSubscription: ISubscription<MetaModule>;

this.hubConnection = new HubConnectionBuilder()
       .withUrl(this.href + '/api/hub/pathToTheHub')
       .withAutomaticReconnect()
       .build();

更改为:

private hubConnection: signalR.HubConnection;
private streamingSubscription: signalR.ISubscription<MetaModule>;

this.hubConnection = new signalR.HubConnectionBuilder()
      .withUrl(this.href + '/api/hub/pathToTheHub')
      .withAutomaticReconnect()
      .build();

这些更新后,我们的流媒体处理速度显着加快。

关于javascript - 是否可以在 Web Worker 中创建 signalR 流连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59952085/

相关文章:

android - 是否可以在没有 APNS 的情况下发送推送通知(使用 signalR)?

azure - Azure 上的 SignalR 聊天

asp.net-mvc - SignalR 似乎减慢了我的 MVC/Azure 应用程序的启动速度

javascript - Google Chart 单独的条形颜色

javascript - 如何从 JavaScript 函数返回 promise ?

angular - 如何从 http 请求将数据传递给 ng2-smart-table renderComponent?

angular - 在使用 karma 的 Angular 单元测试中 dispatchEvent() 和 triggerEventHandler() 之间有什么区别?

带有 Google Drive Realtime API 的 Angular 2

javascript - 滚动包含来自不同域的页面的 iframe

javascript - 清除匿名 setInterval