背景:主 project 頁面中會將視頻存儲到云端后獲得 ID ,然后用 ID 調用 后端API POST到數據庫后拿到掛載頁面URL,接著傳入視頻分享組件(由于視頻分享子組件的目標是分享視頻掛載頁面,所以前置步驟不能少)
const recordBlob = await projectRunnerRef.value?.stopRecording?.()await projectRunnerRef.value?.pauseGame()console.log('錄制已停止,獲得 Blob:', recordBlob)if (!recordBlob) {toaster.error('錄制失敗,未獲得錄制數據')isRecording.value = falsereturn}// 將 Blob 轉換為 File 對象const fileExtension = recordBlob.type?.includes('webm') ? 'webm' : 'mp4'const recordFile = new globalThis.File([recordBlob], `recording_${Date.now()}.${fileExtension}`, { type: recordBlob.type || 'video/webm' })recording.value = recordFiletry {const projectFile = createProjectFile(recordFile)const RecordingURL = await saveFile(projectFile) // 存儲到云端獲得視頻存儲URL
遇到問題:通過查看網絡通信發現傳輸到云端時間很長,所以頁面上就像卡住了一樣一直等待視頻分享彈窗彈出
解決思路:惰性異步處理-不讓阻塞其他執行。將原先先把所有必須的內容拿到再彈出彈框變成先加載彈窗,具體里面要用到視頻掛載URL的地方其實就是生成二維碼的地方,那么寫成 'generating' 來優化交互體驗,那么就需要將原先 props 傳輸 recording 變成一個 Promise 來異步處理
const props = defineProps<{recording: Promise<RecordData>,
那么接收的是一個 Promise 而非直接的數據,從而允許異步加載,避免阻塞UI渲染,實現了數據與UI的解耦
那么從 project 父組件獲得video(可選值,用于首屏展示),同時傳入Promise實例用于并行處理
在云端 cloud.ts 中
export async function saveFiles(files: Files,signal?: AbortSignal
): Promise<{ fileCollection: FileCollection; fileCollectionHash: string }> {const fileCollection = Object.fromEntries(await Promise.all(Object.keys(files).map(async (path) => [path, await saveFile(files[path]!, signal)] as const)))const fileCollectionHash = await hashFileCollection(fileCollection)return { fileCollection, fileCollectionHash }
}
通過 Promise.all 處理多文件上傳
然后在 錄屏組件中寫一個副作用回調函數用于更新
async function loadRecordingData() {if (currentRecording.value) returntry {currentRecording.value = await props.recordingawait updateVideoSrc()} catch (error) {console.error('加載錄制數據失敗:', error)}
}
在 watch 中回調
watch(() => props.visible, (newVisible) => {if (newVisible) {// 重置狀態jumpUrl.value = ''qrCodeData.value = ''// 立即更新視頻源(優先使用 props.video)updateVideoSrc()// 加載錄制數據(用于分享參數)loadRecordingData()