如何使用Javascript / AJAX以特定顺序加载多个文件的内容

时间:2018-07-09 14:29:54

标签: javascript json ajax

我正在使用JS / AJAX在页面上显示多个文件的内容。这些文件是动态生成的,并使用for循环进行加载。有一个文件包含该集合的元数据,包括需要加载多少其他文件。其他文件的文件名中有一个数字,我通过请求“ file_ [loop_index] .json”来加载它们。

问题是,每个json文件中的数据量也是任意的,并且AJAX调用将首先以最小文件的顺序完成。我想按名称而不是大小顺序显示数据。

这是一个简化的示例,假设我们要显示一本书的内容:

function get(url) {
  return new Promise(function(resolve, reject) {
    var req = new XMLHttpRequest();
    req.open('GET', url);

    req.onload = function() {
      if (req.status == 200) {
        resolve(req.response);
      }
      else {
        reject(Error(req.statusText));
      }
    };

    req.onerror = function() {
      reject(Error("Network Error"));
    };

    req.send();
  });
}

get('toc.json').then(function(response) {
  chapters = JSON.parse(response)["chapters"];
  return chapters;
}).then(function(levels) {
  for (i = 0; i < chapters; i++) {
    (function (i) {
      get("chap".concat(i,".json")).then(function(response) {
      console.log(response);

  })
  }(i));
  }
  });

toc.json:

{ "chapters": 2 }

chap0.json:

{ "text" : "00000" }

chap1.json:

{ "text" : "1" }

结果将是:

{ "text" : "1" }
{ "text" : "00000" }

好像我要切换每个文件中的字符数一样,结果将是:

{ "text" : "0" }
{ "text" : "11111" }

无论文件大小如何,我都想在带有“ 1”的行之前打印带有“ 0”的行。

我不能使用async / await,因为我的页面必须在IE11中工作,并且不支持箭头功能。

我想到的解决方案是将内容存储在数组中,从for循环返回该内容,并显示内容,即:

尝试的解决方案:

var tempArray = [];

function get(url) {
  return new Promise(function(resolve, reject) {
    var req = new XMLHttpRequest();
    req.open('GET', url);

    req.onload = function() {
      if (req.status == 200) {
        resolve(req.response);
      } else {
        reject(Error(req.statusText));
      }
    };

    req.onerror = function() {
      reject(Error("Network Error"));
    };

    req.send();
  });
}

get('toc.json').then(function(response) {
  chapters = JSON.parse(response)["chapters"];
  return chapters;
}).then(function(levels) {
  for (i = 0; i < chapters; i++) {
    (function(i) {
      get("chap".concat(i, ".json")).then(function(response) {
        console.log(response);
        tempArray[i] = response;

      })
    }(i));
  }
  return tempArray;
}).then(function(response) {
    console.log(response);
  }

);

但是最终的console.log(response)产生:

Array[]

我想这失败了,因为在实际的AJAX调用完成之前,promise序列正在通过for循环部分。如果我能弄清楚如何等待他们完成任务,我会在那里,但此刻我很沮丧。

可以在其他情况下使用的另一种解决方案是动态生成html的一部分,并使用相应的文件内容更新正确的元素。不幸的是,对于我的特定用例,这不是一个选择。

有帮助吗?谢谢。

2 个答案:

答案 0 :(得分:1)

弯腰使用诺言。为什么不只将名称包含在数组中,并让一个函数进行获取,更新计数器并再次调用该函数?

var listOfFiles=["fileList.txt”],
    cnt=0, 
    oReq = new XMLHttpRequest();

function reqListener () {
  if (listOfFiles[0]=="fileList.txt") {
    listOfFiles = this.responseText.split(",");
  }
  else { 
    processFile(this.responseText);
    cnt++;
  }
  getFile();
}

oReq.addEventListener("load", reqListener);
function getFile() { 
  if (cnt >= listOfFiles.length) return; 
  oReq.open("GET", listOfFiles[cnt]);
  oReq.send(); 
} 
getFile();

答案 1 :(得分:1)

使用Promise.all(示例中已删除XHR,但仍使用Promises)。

function getTOC() {
  var jsonStr = JSON.stringify({
    chapters: 2,
  });
  return Promise.resolve(jsonStr);
}

function getChapter(i) {
  return Promise.resolve("chapter " + i);
}

getTOC()
  .then(function(response) {
    var chapters = JSON.parse(response)["chapters"];
    return chapters;
  })
  .then(function(chapters) {
    var promises = [];
    for (i = 0; i < chapters; i++) {
      promises.push(getChapter(i));
    }
    return Promise.all(promises);
  })
  .then(function(results) {
    // results is an array of results, ordered as expected
    console.log(results);
  });