我正在使用 Angular 8 和 singalR 从服务器进行图像流传输。
我注意到流媒体会减慢我的 UI 渲染速度。 我希望整个流媒体部分转移到 Web Worker,并且仅将有值(value)的内容从 Web Worker 发送到 UI 部分。
我没有代码示例,因为我不确定我的想法是否可行。
任何人都可以给我一些提示或发帖,因为我在其中没有找到任何有关 Web Worker 和 Web 套接字(signalR)连接的信息。
最佳答案
经过一番研究,我终于完成了这个。 这是可能的,并且有一些提示:
https://angular.io/guide/web-worker 创建 Web Worker,ng 生成 webWorker 是该命令,Angular 将为您设置环境。 如果您在没有此命令的情况下执行此操作,则需要执行其他工作。请检查文档。
安装@microsoft/signalr 库,而不是@aspnet/signalr。我在 Web Worker 中与 @aspnet/signalr 建立连接时遇到问题。
然后从我的组件中调用工作人员来建立连接:
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/