Можно ли создать потоковое соединение signalR в веб-работнике? - PullRequest
1 голос
/ 28 января 2020

Я использую Angular 8 и singalR для потоковой передачи изображений с сервера.

Я заметил, что потоковая передача замедляет рендеринг пользовательского интерфейса. Я хочу, чтобы вся потоковая часть перешла в Web Worker, и только ценный контент отправлялся из Web Worker в UI.

У меня нет примера кода, так как я не уверен, что моя идея вообще возможна.
Может кто-нибудь дайте мне несколько советов, или пост, так как я не нахожу в них ничего о веб-работниках и подключении к веб-сокету (signalR).

1 Ответ

0 голосов
/ 20 февраля 2020

После некоторых исследований я наконец закончил это. Это возможно, и есть несколько советов для этого:

1) https://angular.io/guide/web-worker Создайте веб-работника, ng generate webWorker, это команда для этого, и Angular настроит среду для вы. Если вы сделаете это без этой команды, вам придется проделать дополнительную работу. Пожалуйста, проверьте документацию для этого.

2) Установите библиотеку @ microsoft / signalr, а не @ aspnet / signalr. У меня была проблема с установкой sh соединения в веб-работнике с @ aspnet / signalr.

3) Затем из моего компонента я позвонил работнику, чтобы установить sh соединение:

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». Если это так, я создаю новый экземпляр класса и устанавливаю sh соединение с концентратором в конструкторе классов. Я посылаю рабочий класс в класс тоже. После этого за все потоковые запросы отвечает объект класса.

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> {
    // standard connection to hub...
  }

}

// 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);
  }
});
...