概述心跳与重连能显著提升弱网下的可靠性。本文展示进度持久化与重连后的续传。心跳与续传function openDB(name) { return new Promise((resolve, reject) => { const r = indexedDB.open(name, 1); r.onupgradeneeded = () => { const db = r.result; if (!db.objectStoreNames.contains('ws')) db.createObjectStore('ws'); }; r.onsuccess = () => resolve(r.result); r.onerror = () => reject(r.error); }); } async function saveIndex(name, idx) { const db = await openDB('wsup'); const tx = db.transaction('ws','readwrite'); tx.objectStore('ws').put(idx, name); await new Promise((res, rej) => { tx.oncomplete = res; tx.onerror = () => rej(tx.error); }); db.close(); } async function loadIndex(name) { const db = await openDB('wsup'); const tx = db.transaction('ws','readonly'); const req = tx.objectStore('ws').get(name); const v = await new Promise((res, rej) => { req.onsuccess = () => res(req.result||0); req.onerror = () => rej(req.error); }); db.close(); return v; } async function connect(url, onOpen) { const ws = new WebSocket(url); ws.binaryType = 'arraybuffer'; await new Promise(res => { ws.onopen = res; }); const timer = setInterval(() => ws.readyState === 1 && ws.send(JSON.stringify({ type:'ping' })), 5000); ws.onclose = () => clearInterval(timer); onOpen(ws); } async function resumeUpload(url, file, size = 512*1024) { const name = file.name; const startIdx = await loadIndex(name); await connect(url, async ws => { let i = 0; for (let o=0;o<file.size;o+=size) { const b = file.slice(o, o+size); const ab = await b.arrayBuffer(); if (i < startIdx) { i++; continue; } const head = new TextEncoder().encode(JSON.stringify({ type:'chunk', index:i, name })); const merged = new Uint8Array(head.length + ab.byteLength); merged.set(head, 0); merged.set(new Uint8Array(ab), head.length); ws.send(merged); i++; ws.onmessage = async e => { const m = JSON.parse(new TextDecoder().decode(new Uint8Array(e.data))); if (m.type === 'ack') await saveIndex(name, m.index+1); }; } }); }

发表评论 取消回复