JavaScript无Promise多文件加载:代码是否会漏触发allDone?
问题描述
我有一个FileLoader,使用方式如下:
const loader = new FileLoader(); loader.load(path1, data => { // onLoad function }); loader.load(path2, data => { // onLoad function });
我知道可以将该加载器包装成Promise,再用Promise.allSettled处理结果。但我仅需在所有文件加载完成时调用一个函数,无需检查失败情况,因此编写了如下代码:
let toload = num_files; for(let i = 0; i < num_files; i++) { loader.load(path[i], data => { // process data toload--; if(toload == 0) allDone(); } }
考虑到加载的异步特性,这段代码是否会出现错误,导致错过toload == 0的条件?
回答
这段代码不会出现错过toload == 0的情况,原因很明确:
- JavaScript的异步回调(这里的
onLoad函数)运行在单线程的事件循环中,不存在多线程并发修改toload的竞态问题,每次toload--都是原子性的操作。 - 最后一个完成加载的文件触发回调时,
toload会被准确减到0,必然触发allDone()。
不过有两个细节需要注意:
- 如果
num_files本身为0,循环不会执行,allDone()也不会被调用,建议在循环前补充判断:
let toload = num_files; if (toload === 0) { allDone(); return; } for(let i = 0; i < num_files; i++) { loader.load(path[i], data => { // process data toload--; if(toload == 0) allDone(); }); }
- 若某个文件加载失败(比如网络错误、文件不存在),对应的
onLoad回调不会执行,toload永远无法减到0,allDone()也就永远不会触发。如果你的业务需要在所有请求(无论成功失败)结束后执行allDone(),还是建议用Promise包装后配合Promise.allSettled,能完整捕获所有请求的结束状态。
内容的提问来源于stack exchange,提问作者user9163823
相关产品推荐
相关产品推荐

