无法同时获取 csv 的文件名及其在 zip 中异步读取的内容
Can't get both filename of csv and its content with async read inside zip
我正在尝试编写一个函数来加载一个包含多个其他 zip 文件的 zip 文件,遍历这些文件并提取找到的所有 csv 文件以合并并将结果提取到一个聚合的 csv 中。我 运行 遇到的问题是我无法使用异步将 csv 的内容映射到它的文件名或目录。这是一个片段,其中 myzip2 是一个 JSZIP 对象,files 是文件名的字典,csvfiles 是我的输出数组。
for (var key in files) {
if ( files[key].name.includes('.csv') ) {
myzip2.file( files[key].name ).async("string").then( function(result) {
csvfiles.push( $.csv.toArrays(result) ); // contains the csv content
csvfiles.push( files[key].name ); // undefined in async
});
)
)
我想同时推送csv内容和文件名,但是文件名在函数内未定义。我怎么才能得到它?我没有太多机会用谷歌搜索我的问题,我可能缺少正确的措辞。
谢谢
如果有人遇到同样的问题,将文件名与内容匹配是箭头函数修复的闭包问题,但匹配正确的 zip 文件名是 JSZip 附加到当前对象的问题。如果需要清除旧的,请使用new JSZip()
。
完整代码,zipfiles 是 mainzip 中包含的 zipfiles 名称列表
var csvfiles = []
for (var i = 0; i < zipfiles.length; i++) {
let thiszipname = zipfiles[i];
let thiszip = mainzip.file( thiszipname ).async("blob");
var newzip = new JSZip();
newzip.loadAsync( thiszip ).then(
subzip => {
let subfiles = subzip.files;
Object.keys(subfiles).forEach( filename => {
if ( filename.includes('.csv') ) {
subzip.file( filename ).async("string").then(
readData => {
var obj = $.csv.toObjects(readData); // works great
obj['csvfile'] = filename // correct file
obj['zipfile'] = thiszipname; // incorrect zipfile...
csvfiles.push( obj );
}
);
}
})
}
)
} console.log(csvfiles)
问题与 files
变量的词法范围有关。与async
.
无关
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
当您在循环中执行此操作时,您需要处理“循环中的闭包”问题。
请查看“在循环中创建闭包:一个常见错误”部分,紧接着 link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
你应该用箭头函数替换你的匿名函数,它会起作用。
for (var key in files) {
// It's important to set the value of the `files[key]` to the separate variable.
// Because otherwise the last element of the `files` will be captured in the closure for the expression `files[key]`.
const fileName = files[key].name;
myzip2
.file(fileName)
.async("string")
// Arrow function `result => {}` creates a closure that captures `fileName` variable from the external scope
.then(result => {
csvfiles.push($.csv.toArrays(result));
csvfiles.push(fileName);
});
}
我正在尝试编写一个函数来加载一个包含多个其他 zip 文件的 zip 文件,遍历这些文件并提取找到的所有 csv 文件以合并并将结果提取到一个聚合的 csv 中。我 运行 遇到的问题是我无法使用异步将 csv 的内容映射到它的文件名或目录。这是一个片段,其中 myzip2 是一个 JSZIP 对象,files 是文件名的字典,csvfiles 是我的输出数组。
for (var key in files) {
if ( files[key].name.includes('.csv') ) {
myzip2.file( files[key].name ).async("string").then( function(result) {
csvfiles.push( $.csv.toArrays(result) ); // contains the csv content
csvfiles.push( files[key].name ); // undefined in async
});
)
)
我想同时推送csv内容和文件名,但是文件名在函数内未定义。我怎么才能得到它?我没有太多机会用谷歌搜索我的问题,我可能缺少正确的措辞。
谢谢
如果有人遇到同样的问题,将文件名与内容匹配是箭头函数修复的闭包问题,但匹配正确的 zip 文件名是 JSZip 附加到当前对象的问题。如果需要清除旧的,请使用new JSZip()
。
完整代码,zipfiles 是 mainzip 中包含的 zipfiles 名称列表
var csvfiles = []
for (var i = 0; i < zipfiles.length; i++) {
let thiszipname = zipfiles[i];
let thiszip = mainzip.file( thiszipname ).async("blob");
var newzip = new JSZip();
newzip.loadAsync( thiszip ).then(
subzip => {
let subfiles = subzip.files;
Object.keys(subfiles).forEach( filename => {
if ( filename.includes('.csv') ) {
subzip.file( filename ).async("string").then(
readData => {
var obj = $.csv.toObjects(readData); // works great
obj['csvfile'] = filename // correct file
obj['zipfile'] = thiszipname; // incorrect zipfile...
csvfiles.push( obj );
}
);
}
})
}
)
} console.log(csvfiles)
问题与 files
变量的词法范围有关。与async
.
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
当您在循环中执行此操作时,您需要处理“循环中的闭包”问题。
请查看“在循环中创建闭包:一个常见错误”部分,紧接着 link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
你应该用箭头函数替换你的匿名函数,它会起作用。
for (var key in files) {
// It's important to set the value of the `files[key]` to the separate variable.
// Because otherwise the last element of the `files` will be captured in the closure for the expression `files[key]`.
const fileName = files[key].name;
myzip2
.file(fileName)
.async("string")
// Arrow function `result => {}` creates a closure that captures `fileName` variable from the external scope
.then(result => {
csvfiles.push($.csv.toArrays(result));
csvfiles.push(fileName);
});
}