docs(canvas): explain legacy persistence and upload cleanup
This commit is contained in:
@@ -30,9 +30,11 @@ export function useImageUploads(workspace: string, commit: (draft: ImageUploadDr
|
||||
if (job.status === "uploading") return;
|
||||
job.status = "uploading"; job.error = undefined; job.controller = new AbortController(); changed();
|
||||
try {
|
||||
// Promise.all 不会因 ready 拒绝自动中止上传;失败 UI 可先出现,而底层请求仍可能完成。
|
||||
const [asset] = await Promise.all([uploadCanvasImage(api, workspace, job.file, job.file.name, job.controller.signal, job.key), job.ready || Promise.resolve()]);
|
||||
// 结果返回后核对挂载、Map内仍是同一个job且未取消,旧任务不能写到后来同ID的新任务。
|
||||
if (!mounted.current || pending.current.get(job.node.id) !== job || job.controller.signal.aborted) return;
|
||||
// commit 是同步调用,不等待网络 ACK;抛错不会自动撤销它此前已发布的本地修改。
|
||||
job.asset = asset; onCommit.current(job, asset); job.status = "uploaded"; changed();
|
||||
} catch (error) { if (mounted.current && pending.current.get(job.node.id) === job && !job.controller.signal.aborted) { job.status = "failed"; job.error = errorText(error); changed(); } }
|
||||
}
|
||||
@@ -42,11 +44,13 @@ export function useImageUploads(workspace: string, commit: (draft: ImageUploadDr
|
||||
let value: ImageUploadDraft;
|
||||
try { value = draft(localURL); } catch (error) { URL.revokeObjectURL(localURL); throw error; }
|
||||
const job: ImageUploadJob = { ...value, file, localURL, key: crypto.randomUUID(), status: "failed", controller: new AbortController() };
|
||||
// 节点 ID 必须由草稿工厂保证唯一;同 ID set 会替换旧任务,但此处不会 abort/revoke 被替换的任务。
|
||||
pending.current.set(job.node.id, job); changed();
|
||||
// Browser decoding runs locally, concurrently with the original-byte upload.
|
||||
// 纯图片并行解码自然尺寸,限制初始长宽不超过480(不主动放大),再分别设置至少24px的显示尺寸。
|
||||
if (job.node.data.kind === "plain-image") {
|
||||
job.ready = new Promise<void>((resolve,reject) => {
|
||||
// 这个 Image 解码没有接入 controller 的取消,也没有显式移除 onload/onerror;回调以 Map 身份拒绝已移除任务。
|
||||
const image = new window.Image(); image.onload = () => {
|
||||
if (pending.current.get(job.node.id) !== job) { resolve(); return; }
|
||||
// 分别钳制到最小24可能改变极端长宽比;这里只初始化节点和style尺寸,不重编码上传文件。
|
||||
@@ -60,6 +64,7 @@ export function useImageUploads(workspace: string, commit: (draft: ImageUploadDr
|
||||
void run(job);
|
||||
return job;
|
||||
}
|
||||
// 每次重试仍调用上传接口,不直接采用 job.asset;幂等依赖相同 key,ready 失败也不会自动回滚服务端资源。
|
||||
// hasPending包含失败但不包含uploaded,active只看uploading;loaded仅在正式图片加载后移除已上传预览。
|
||||
// retry复用job及幂等键;若ready曾拒绝,重试不会在这里重建尺寸解码Promise。
|
||||
return { jobs, hasPending:()=>[...pending.current.values()].some(job=>job.status!=="uploaded"), active: jobs.some((job) => job.status === "uploading"), start, retry: (id: string) => { const job = pending.current.get(id); if (job) void run(job); }, remove, loaded: (id: string) => { if (pending.current.get(id)?.status === "uploaded") remove(id); } };
|
||||
|
||||
Reference in New Issue
Block a user