Javascript 组合了来自不同范围的多个数组



下面是一个函数,它应该使用chaptersArry来获取每个章节的项目,并将它们放入一个新的数组中*原始章节数据和项目数据一起*称为itemsArr

function get_items(chaptersArry){
  for ( var ii = 0, l = chaptersArry.length; ii < l; ii++ ) {
    console.log(chaptersArry[ii].id+" *****");  // this returns the correct data

    // now I am using each chapter ID from above to $.get the chapter items..... 
    var api_url = '/collections/' + chaptersArry[ii].id + '/contents.json';
    $.get(api_url, function(items) {
      // for each chapter loop through items and push them to itemsArr.
      for ( var i = 0, l = items.collection_contents.length; i < l; i++ ) {
        console.log(chaptersArry[ii].id); // returns incorrect data 
        itemsArr.push({
            series_id : chaptersArry[ii].series_id, 
            series_name : chaptersArry[ii].series_name,
            chapter_id : chaptersArry[ii].id, 
            chapter_name : chaptersArry[ii].name,
            chapter_display_name : chaptersArry[ii].display_name,
            chapter_data : items.collection_contents[i]
        });
      }
    });
  }
}

与 Kamyar Infinity 的答案一样,您需要使用闭包或使用带有 let 的块范围来获取$.get()回调中的正确数据,但是,这不是问题的症结所在。由于您需要异步返回数据,因此需要使用承诺。以下是您可以做到这一点的方法:

工作演示

function get_items(chaptersArry){
  return new Promise(function (resolve, reject) {
    var promises = [];
    for (let ii = 0, l = chaptersArry.length; ii < l; ii++ ) {
      console.log(chaptersArry[ii].id+" *****");  // this returns the correct data
      // now I am using each chapter ID from above to $.get the chapter items..... 
      var api_url = '/collections/' + chaptersArry[ii].id + '/contents.json';
      var promise = new Promise(function (_resolve, _reject) {
        $.get(api_url, function(items) {
          var itemsArr = [];
          // for each chapter loop through items and push them to itemsArr.
          for ( var i = 0, l = items.collection_contents.length; i < l; i++ ) {
            itemsArr.push({
              series_id : chaptersArry[ii].series_id, 
              series_name : chaptersArry[ii].series_name,
              chapter_id : chaptersArry[ii].id, 
              chapter_name : chaptersArry[ii].name,
              chapter_display_name : chaptersArry[ii].display_name,
              chapter_data : items.collection_contents[i]
            });
          }
          _resolve(itemsArr);
        });
      });
      promises.push(promise);
    }
    Promise.all(promises).then(function (values) {
      resolve(values);
    });
  });
}
get_items(chaptersArry).then(function (results) {
  // flatten array of results from each $.get()
  console.log([].concat(...results));
});

我看到的主要问题是,当你使用var时,循环结束时l-1 ii的值,因为var不是基于块的声明,并且所有函数都将获得同一变量的值。现在,您有两种选择。

你可以

使用 let ,如果你可以使用 ES6:

for ( let ii = 0, l = chaptersArry.length; ii < l; ii++ ) {
...

如果没有,您可以使用IIFE

for ( var ii = 0, l = chaptersArry.length; ii < l; ii++ ) {
    (function(ii){
       ...
     })(ii);
}

您可以使用 Function.bind:

$.get(api_url, function(items) {
  var ii = this;
  // for each chapter loop through items and push them to itemsArr.
  for ( var i = 0, l = items.collection_contents.length; i < l; i++ ) {
    console.log(chaptersArry[ii].id); // returns incorrect data 
    itemsArr.push({
        series_id : chaptersArry[ii].series_id, 
        series_name : chaptersArry[ii].series_name,
        chapter_id : chaptersArry[ii].id, 
        chapter_name : chaptersArry[ii].name,
        chapter_display_name : chaptersArry[ii].display_name,
        chapter_data : items.collection_contents[i]
    });
  }
}.bind(ii));

这个问题有更好的解决方案。但这可能是最简单的。这可能是一个重复的,因为它与JavaScript闭包相关。

最新更新