多视频上传:socket.on监听器进度与索引关联错误修复
多视频上传时Socket进度监听关联错误的解决方案
问题核心
同时上传多个视频时,socket.on('upload-progress')和socket.on('upload-success')监听器会触发所有视频的状态更新,且监听器内的index值无法正确绑定对应视频,导致进度和ID被错误分配。
解决方案
核心思路是给每个上传任务分配唯一标识,让前后端通过这个标识关联任务,确保事件只触发对应视频的状态更新。
1. 前端代码修改
生成唯一uploadId,上传时携带该标识,监听事件时通过uploadId匹配对应视频索引,上传完成后移除监听器避免内存泄漏:
async function handleUploadLectureVideo({ files }: any, index: number) { const file = files[0]; // 生成唯一上传ID(浏览器环境可用crypto.randomUUID,其他环境可自定义唯一值) const uploadId = crypto.randomUUID(); socket.emit("upload-file", { file, fileMeta: { originalName: file.name, }, name: file.name, uploadId, // 携带唯一标识 }); // 进度监听函数:仅处理当前uploadId的事件 const handleProgress = (eventData: { uploadId: string; percentage: number }) => { if (eventData.uploadId === uploadId) { setValue(`courseLectures.${index}.uploadingProgress`, eventData.percentage); } }; // 成功监听函数:仅处理当前uploadId的事件,完成后移除监听器 const handleSuccess = (eventData: { uploadId: string; id: string }) => { if (eventData.uploadId === uploadId) { setValue(`courseLectures.${index}.lectureVideo`, eventData.id); // 移除监听器,避免内存泄漏 socket.off("upload-progress", handleProgress); socket.off("upload-success", handleSuccess); } }; // 绑定监听器 socket.on("upload-progress", handleProgress); socket.on("upload-success", handleSuccess); }
2. 后端代码修改
接收前端传来的uploadId,在发送进度、成功、失败事件时携带该标识,让前端能精准匹配任务:
async handleFileUpload(@MessageBody() data: any, @ConnectedSocket() client: Socket) { const file = data.file; const meta = data.fileMeta; const name = data.name; const uploadId = data.uploadId; // 获取前端传入的唯一标识 const filename = this.getCompleteFileName(meta); const completePath = join('video-lectures', filename); await promises.writeFile(completePath, file); this.vimeoClient.upload( completePath, { name }, async (uri: string) => { const video = new Video(); video.url = uri; const result = await this.videoRepository.save(video); // 返回uploadId与视频ID client.emit('upload-success', { uploadId, id: result.id }); }, (bytesUploaded: number, bytesTotal: number) => { const percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2); // 返回uploadId与进度百分比 client.emit('upload-progress', { uploadId, percentage }); }, error => { console.log('Failed because: ' + error); // 失败事件同样携带uploadId client.emit('upload-failed', { uploadId, error }); }, ); }
额外优化
- 建议添加
upload-failed事件的监听逻辑,同样通过uploadId匹配任务,并在失败时移除对应监听器 - 组件卸载时,调用
socket.off()移除所有相关监听器,彻底避免内存泄漏
内容的提问来源于stack exchange,提问作者Abdul Ahad
相关产品推荐
相关产品推荐

