闭包可为每个分片独立维护状态,避免全局污染;通过createChunkTracker工厂函数捕获chunkIndex等参数,返回含update、getProgress等方法的对象,在XMLHttpRequest中绑定事件处理器,实现隔离更新与安全聚合总进度。

闭包可以自然地为每个分片(chunk)维护独立的状态,避免全局变量污染和状态混淆。核心思路是:在创建上传任务时,用闭包捕获当前 chunk 的索引、大小、已上传字节数等私有状态,并通过返回的函数持续更新和读取它。
封装 chunk 状态管理器
为每个 chunk 创建一个闭包作用域,内部保存其进度相关数据:
- 定义一个工厂函数 createChunkTracker,接收 chunkIndex、chunkSize、totalSize 等参数
- 在闭包内声明私有变量如 loaded = 0、isCompleted = false
- 返回一个对象,暴露 update(loadedBytes)、getProgress()、markComplete() 等方法
配合 XMLHttpRequest 或 Fetch 使用
在上传回调中调用闭包内的更新方法,确保状态只影响对应 chunk:
- 使用 XMLHttpRequest.upload.onprogress 时,传入闭包返回的 update 方法作为事件处理器
- 成功响应后调用 markComplete(),该操作不会干扰其他 chunk 的状态
- 例如:xhr.upload.onprogress = tracker.update; —— 此处 tracker 是某次调用 createChunkTracker 得到的实例
聚合所有 chunk 进度用于整体展示
外部可安全汇总各闭包的状态,实现总进度计算:
- 将每个 chunk 的 tracker 实例存入数组(如 trackers = [])
- 定时或在每次更新后遍历 trackers,调用 getProgress() 获取各自完成比例
- 总进度 = sum(已完成字节数) / totalSize,其中每个“已完成字节数”来自对应闭包内部的 loaded 值
避免常见陷阱
闭包虽好,但需注意生命周期与内存管理:
- 不要在循环中直接用 var i 创建闭包,应使用 let 或立即执行函数确保每个 chunk 捕获正确的索引
- 上传完成后及时从 trackers 数组中移除或置空引用,防止长期驻留内存
- 若使用 AbortController,可在 tracker 中绑定 abort 逻辑,使取消操作也作用于当前 chunk 的闭包状态










