Javascript如何使用FileReader.onload从多个json文件加载内容?

Javascript如何使用FileReader.onload从多个json文件加载内容?,javascript,json,filereader,onload,Javascript,Json,Filereader,Onload,我需要上传多个json文件,并将其内容存储在一个数组中。我的目标是以某种方式将它们合并在一起。我试着这样做: var results = new Array(); //global variable document.getElementById('uploadId').onclick = function () { var files = document.getElementById('selectFiles').files; for (var i = 0; i <

我需要上传多个json文件,并将其内容存储在一个数组中。我的目标是以某种方式将它们合并在一起。我试着这样做:

var results = new Array();    //global variable

document.getElementById('uploadId').onclick = function () {
   var files = document.getElementById('selectFiles').files;

   for (var i = 0; i < files.length; i++) {
       var fr = new FileReader();

       fr.onload = function (e) {
           console.log(e);
           var result = JSON.parse(e.target.result);
           results.push(result);
       }

       fr.readAsText(files.item(i));
   }
   process();
}; 

function process(){
   console.log(results); // displays everything as expected
   console.log(results.length); // returns 0 ?!
   console.log(results[0]) // return undefined ?!
}
var results=new Array()//全局变量
document.getElementById('uploadId')。onclick=function(){
var files=document.getElementById('selectFiles').files;
对于(var i=0;i
然后,在将
结果
数组记录到控制台中时,所有内容都按预期显示。但是当我尝试遍历数组时,所有单个对象都是未定义的。和
results.length
也返回
0


我想异步性可能有问题。您知道如何解决这个问题吗?

您可以将预定义对象绑定到加载函数(或定义范围和/或全局变量),该函数存储两个值:filesToProcess和fileprocessed。在每次onload时,递增fileprocessed,直到到达filesToProcess。这是,如果你想保持旧的浏览器,如IE或旧的Safari版本的支持

可悲的是,我只能在理论上证明它,没有任何实际的测试

document.getElementById('uploadId').onclick = function () {
   var files = document.getElementById('selectFiles').files,
       param = {filesProcessed: 0, filesToProcess: files.length};

   for (var i = 0; i < files.length; i++) {
       var fr = new FileReader();

       fr.onload = function(e){
           results.push(JSON.parse(e.target.result));

           //REM: this being param
           this.filesProcessed++;

           if(this.filesProcessed === this.filesToProcess){
               process()
           }
       }.bind(param)

       fr.readAsText(files.item(i));
   }
};
document.getElementById('uploadId')。onclick=function(){
var files=document.getElementById('selectFiles').files,
param={filesProcessed:0,filesToProcess:files.length};
对于(var i=0;i
通常,您可以通过将等待文件的代码(在本例中为
进程
)作为
文件读取器
侦听器的一部分来避免此问题,以便在完成后发生。我想不出这样一种情况:用户需要将多个文件上载到同一个
输入
,而无法单独处理它们(即,如果需要两个文件同时处理,请将它们分别放入
输入
并使用提交按钮)

但是,如果您曾经这样做过,我的建议是使用
async
/
wait
或ES6承诺。下面是我将所有文件作为JSON读入数组的方法,然后对它们进行处理

const results=[];
const input=document.querySelector('input[type=“file”]”);
input.addEventListener('change',async()=>{
等待承诺.all([…input.files].map(文件=>新承诺((解析,拒绝)=>{
const reader=new FileReader();
reader.onloadend=()=>{
试一试{
解析(results.push(JSON.parse(reader.result));
}捕捉(错误){
//返回空值;忽略非JSON(或执行其他操作)
log('Please use.json!');
解决();
}
}
reader.readAsText(文件);
})));
//做事
控制台日志(结果);
console.log(results.length);
console.log(结果[0]);
});


当它被记录时,
结果
旁边是否有一个蓝色的“
i
”符号?@matthew-e-brown是的,它确实是浏览器的控制台告诉你,当你在控制台中查看时,该数据段被评估了,而不是在到达它的行时。这意味着(可能)它在
process()
运行时是空的,直到后来您检查它是否已被实际填充。@matthew-e-brown所以我需要在调用process()之前等待一段时间,直到添加到数组中为止?您需要一次执行
process()
完成。@pelikann请记住,当使用Promissions/Async&等待时,您将失去IE支持。如果答案解决了你的问题,别忘了选择一个被接受的答案!:)我也想到了一个蹩脚的解决办法。我可以将process()包装成5秒的setTimeout,我想它在大多数情况下都会起作用。@pelikann你可以肯定,但我认为说大多数人不赞成这样的解决方案是轻描淡写的;)