循环条件为真但For循环未执行,DOM文件面板填充失败求助
问题:Cordova File插件读取文件后无法填充DOM文件面板
问题现象
尝试用数组filesList填充文件面板,运行应用时:
- 控制台显示
filesList包含文件对象且长度大于0 - DOM中的列表容器未添加任何元素
fillFilePanel函数内的循环代码没有执行(无对应日志输出)
相关代码
sideBar.js
import { FILE_PANEL } from "../../app.js"; export function fillFilePanel(filesList) { console.log(filesList); for (let i = 0; i < filesList.length; i++) { let entries = filesList[i] if (entries.isDirectory == true) { FILE_PANEL.append(`<button id="F${entries.name}" type="button" class="list-group-item list-group-item-action" key="folder" data-toggle="#F${entries.name}Group">${entries.name}</button> <ul class="list-group" id="F${entries.name}Group"> </ul>`); let parentDir = entries.name + '/'; // showSubFolder(parentDir) } else { FILE_PANEL.append(`<button type="button" class="list-group-item list-group-item-action">${entries.name}</button>`); } } }
MainFs.js
import { fillFilePanel } from "./ui/sideBar.js" { //...其他业务代码 let filesList = []; listDir().then(val => (val.forEach((f) => { filesList.push(f); }))); fillFilePanel(filesList) } /** * 读取本地存储并填充侧边栏文件列表 **/ export function listDir(url = '') { return new Promise(function(res, reject) { let path = cordova.file.externalRootDirectory + url window.resolveLocalFileSystemURL(path, function(fs) { const reader = fs.createReader(); reader.readEntries(function(entries) { res(entries) }, (rej) => { return rej }); }, (rej) => { return rej }); }); }
控制台输出示例
[{"isFile":false,"isDirectory":true,"name":".face","fullPath":"/.face/","filesystem":"<FileSystem: sdcard>","nativeURL":"file:///storage/emulated/0/.face/"},{"isFile":false,"isDirectory":true,"name":".audio_param","fullPath":"/.audio_param/","filesystem":"<FileSystem: sdcard>","nativeURL":"file:///storage/emulated/0/.audio_param/"},{"isFile":false,"isDirectory":true,"name":"Music","fullPath":"/Music/","filesystem":"<FileSystem: sdcard>","nativeURL":"file:///storage/emulated/0/Music/"},{"isFile":false,"isDirec ...}]
问题原因
核心是异步执行顺序错误:
listDir()返回Promise,文件读取操作是异步的,then()回调会在文件读取完成后才执行- 调用
listDir()后立刻执行fillFilePanel(filesList),此时filesList还是空数组,循环条件i < filesList.length不成立,循环代码完全没执行 - 控制台后来看到的
filesList有内容,是因为then()回调在fillFilePanel执行完之后才完成并填充了数组,但此时函数已经跑完了
解决办法
方案1:将填充操作放到Promise回调内
修改MainFs.js中的代码,确保在文件读取完成、数组填充后再调用fillFilePanel:
import { fillFilePanel } from "./ui/sideBar.js" { //...其他业务代码 let filesList = []; listDir().then(val => { val.forEach((f) => { filesList.push(f); }); fillFilePanel(filesList); // 数组填充完成后再调用 }); }
方案2:使用async/await简化异步逻辑
用async/await替代Promise回调,代码更直观:
import { fillFilePanel } from "./ui/sideBar.js" // 用自执行async函数包裹 (async function() { //...其他业务代码 let filesList = await listDir(); // 等待文件读取完成,直接获取结果 fillFilePanel(filesList); })();
额外检查点
- 确认
FILE_PANEL是正确获取的DOM元素,可以在fillFilePanel开头加console.log(FILE_PANEL)验证是否为有效DOM节点 - 循环内添加
console.log(entries),修复异步问题后可以确认循环正常执行
内容的提问来源于stack exchange,提问作者John Delvin
相关产品推荐
相关产品推荐

