Javascript对象排序数组使用显式声明,使用变量时中断

Javascript对象排序数组使用显式声明,使用变量时中断,javascript,arrays,json,sorting,asynchronous,Javascript,Arrays,Json,Sorting,Asynchronous,我正在使用一个返回JSON数据的API,我想按时间顺序对数据进行排序——根据对象的releaseDate(一个整数)属性 数据样本: let all_albums = [ { "releaseDate": 1461913200000, "critic_rating": 69, "user_rating": 57, "average_rating": 63 }, { "releaseDate": 1380006000000, "criti

我正在使用一个返回JSON数据的API,我想按时间顺序对数据进行排序——根据对象的releaseDate(一个整数)属性

数据样本:

let all_albums = [
  {
    "releaseDate": 1461913200000,
    "critic_rating": 69,
    "user_rating": 57,
    "average_rating": 63
  },
  {
    "releaseDate": 1380006000000,
    "critic_rating": 79,
    "user_rating": 75,
    "average_rating": 77
  },
  {
    "releaseDate": 1321344000000,
    "critic_rating": 78,
    "user_rating": 79,
    "average_rating": 78.5
  },
]
如果我将其复制/粘贴到项目中的单独文件中,我可以使用以下方法对其进行排序:

 let sortedAlbums = all_albums.sort(function (a, b) {
    return a.releaseDate - b.releaseDate;
});
然而,如果我尝试在我的项目中实现这一点,我可以以同样的方式迭代JSON,以同样的方式打印到控制台,所有数据都与我上面演示的相同——但是我无法对这个数据集进行排序

我来自python背景,所以异步性对我来说是新的。这有关系吗?或者,如何对刚从API调用的对象进行排序

----------------------------编辑----------------------------------

谢谢大家到目前为止的评论。我已经重构了一些变量,按照您的建议对代码进行了大量清理。尽管如此,当直接从API调用时,问题仍然存在。下面是示例调用的完整代码(尽管使用了经过审查的mashape键)


我稍微整理了一下您的示例代码,但在功能上完全相同。很好

const allAlbums = [
  {
    'releaseDate': 1461913200000,
    'critic_rating': 69,
    'user_rating': 57,
    'average_rating': 63
  },
  {
    'releaseDate': 1380006000000,
    'critic_rating': 79,
    'user_rating': 75,
    'average_rating': 77
  },
  {
    'releaseDate': 1321344000000,
    'critic_rating': 78,
    'user_rating': 79,
    'average_rating': 78.5
  },
];

const sortedAlbums = allAlbums.sort((a, b) => a.releaseDate - b.releaseDate);
console.log(sortedAlbums);
输出:

[
  {
    "releaseDate": 1321344000000,
    "critic_rating": 78,
    "user_rating": 79,
    "average_rating": 78.5
  },
  {
    "releaseDate": 1380006000000,
    "critic_rating": 79,
    "user_rating": 75,
    "average_rating": 77
  },
  {
    "releaseDate": 1461913200000,
    "critic_rating": 69,
    "user_rating": 57,
    "average_rating": 63
  }
]
由于您是Python程序员,这里有一些样式提示。虽然没有官方的标准风格指南,但有一些一般性的建议

使用单引号。只有骆驼箱。双空格,而不是制表符

在处理数组和对象文本时,您几乎总是希望使用
const
<代码>let和
var
仅在将同一命名变量重新指定给不同值时才需要。使用数组和对象时,您可以自由修改它们的属性,因为您没有重新分配变量


在声明函数时,90%的情况下,胖箭头语法将有助于防止处理此的bug。另外10%的时间是胖箭头导致错误的时间。

下面是您的代码可能的样子,并附上一些注释。看起来您正在尝试使用全局变量
allAlbums
,该变量在document ready事件中设置,结果为异步

但您试图在document ready事件处理程序之外使用该变量,因此访问该变量为时过早,因为数据甚至还没有被尝试加载,即使加载数据是异步的,也无法使用值进行设置,因为该值将来可用(如果失败,则根本不可用)

您只能访问document ready中的
allAlbums
,并将其设置为承诺值,以便知道实际值何时可用

如果allAlbums与其他代码共享,那么不要只对其进行排序,因为排序会对其进行变异,也许当您在其他地方使用它时,您不希望它以某种方式进行排序。如果您确实希望对其进行排序,请删除
.map(x=>x)
之前的
.sort

//All albums is the result of asynchronous action so better store it
//  as a result of asynchronous action (promise)
var allAlbums = $.Deferred().resolve([]);
function Album(releaseDate) {
  this.releaseDate = new Date(releaseDate).getTime();
}
const logSorted = (message,albums) =>
  albums.then(
    albums => albums.map(x=>x).sort((a, b) => a.releaseDate - b.releaseDate)
  ).then(
    sortedAlbums=>console.log(message,sortedAlbums)
  );
$(function () {
  //set allAlbums to a promise
  allAlbums = $.ajax({
    url: 'https://api-marcalencc-metacritic-v1.p.mashape.com/person/drake/album',
    type: 'get',
    dataType: 'json',
    headers: {
      "X-Mashape-Key": "----------------------------",
      "Accept": "application/json"
    }
  })
  .then(
    data =>
      data[0].CreditMediaPairItems.map(
        val =>
          new Album(val.Item.ReleaseDate)
      )
  );
  allAlbums.then(
    albums=>
      logSorted(
        "all albums is set with results so should log sorted:",
        albums
      )
  );
});

//it is kind of pointless to try and use all albums outside of he document ready
//  because document ready is an event that you don't know when it happens unless
//  code is inside document ready.
logSorted("all albums should be empty so sorted is empty too",allAlbums);
解决异步问题后,仍然需要排序,下面是一个如何组合函数以构建多列排序的示例:

const-sorter=getter=>comparer=>(a,b)=>
比较器(getter(a),getter(b));
常量比较枚举=(a,b)=>a-b;
const compareStrings=(a,b)=>a>b?1:(ax.releaseDate)(compareNumbers);
const sortSomeStringValue=分类器(x=>x.someString)(比较字符串);
常量排序=(分拣机)=>(a、b)=>{
常数重复=(索引)=>{
if(索引===分拣机长度){
返回0;
}
常数[分拣机,方向]=分拣机[索引];
常数结果=分拣机(a、b);
如果(结果!==0){
返回结果*方向;
}
复发率(指数+1);
}
复发率(0);
};
//有关如何使用的示例:
常量采样数组=[
{someString:“a”,发布日期:3},
{someString:“a”,发布日期:2},
{someString:“a”,发布日期:1},
{someString:“b”,发布日期:3},
{someString:“b”,发布日期:2},
{someString:“b”,发布日期:1},
{someString:“c”,发布日期:3},
{someString:“c”,发布日期:2},
{someString:“c”,发布日期:1}
];
console.log(
“someString降序,然后releaseDate升序”,
JSON.stringify(
样品阵列
.map(x=>x)//复制,这样我们就不会更改原始
.分类(
分类([
[sortSomeStringValue,-1],//按某个字符串降序排序
[sortReleaseDate,1]//按发布日期升序排序
])
),
未定义,
2.
)
);
console.log(
“releaseDate降序,然后字符串升序”,
JSON.stringify(
样品阵列
.map(x=>x)//复制,这样我们就不会更改原始
.分类(
分类([
[sortReleaseDate,-1],//按发布日期降序排序
[sortSomeStringValue,1]//按某个字符串升序排序
])
),
未定义,
2.
)
)
console.log(
“仅限发布日期递减”,
JSON.stringify(
样品阵列
.map(x=>x)//复制,这样我们就不会更改原始
.分类(
分类([
[sortReleaseDate,-1]//按发布日期降序排序
])
),
未定义,
2.
)

)
您提供的数组数据的releaseDate以小“r”开头。但是您正在使用ReleaseDate访问该属性。如果这是一个输入错误,请修复它

当然,这与javascript的异步特性有关。您的ajax调用是异步的。因此,同步javascript在异步ajax调用的成功处理程序启动之前完成执行。您必须在成功处理程序中编写所有异步代码,该处理程序处理来自服务器的返回数据

无法使用异步代码填充全局变量。这意味着将allAlbums变量放入成功处理程序中。将从服务器获得的数据传递给handleDiscography函数。并在成功处理程序中编写所有处理数据的代码。这意味着从服务器检索数据时将执行这些代码

$(function () {
    return $.ajax({
        url: 'https://api-marcalencc-metacritic-v1.p.mashape.com/person/drake/album',
        type: 'get',
        dataType: 'json',
        headers: {
            "X-Mashape-Key": "----------------------------",
            "Accept": "application/json"
        },
        success: function (data) {
                    // these codes will kick in after success handler kicks in
                    var allAlbums = []
                    allAlbums = handleDiscography(data)
                    sortedAlbums(allAlbums)
                    console.log(data)
        },
    })
});
修改handleDiscography功能:

function handleDiscography(data) {
    const allAlbums = [] // declare a local variable
    $.each(album, function (key, val) {
        const releaseDate = val.Item.ReleaseDate;
        addAlbum(releaseDate,allAlbums); // pass the allAlbums to addAlbum variable.array's are passed by reference,remember it !
    });
    return allAlbums // return the allAlbums local variable
}
添加第二个参数以捕获allAlbums变量过程
function handleDiscography(data) {
    const allAlbums = [] // declare a local variable
    $.each(album, function (key, val) {
        const releaseDate = val.Item.ReleaseDate;
        addAlbum(releaseDate,allAlbums); // pass the allAlbums to addAlbum variable.array's are passed by reference,remember it !
    });
    return allAlbums // return the allAlbums local variable
}
function addAlbum(releaseDate,allAlbums) {
    let a = new Album(releaseDate);
    allAlbums.push(a);
}
const sortedAlbums = (allAlbums) => {
    allAlbums.sort((a, b) => a.releaseDate - b.releaseDate)
};
const sortedAlbums = allAlbums.sort((a, b) => a.releaseDate - b.releaseDate);
console.log(sortedAlbums);
$.ajax({
  url: 'https://api-marcalencc-metacritic-v1.p.mashape.com/person/drake/album',
  type: 'get',
  dataType: 'json',
  headers: {
    "X-Mashape-Key": "----------------------------",
    "Accept": "application/json"
  },
  success: function(data) {
    handleDiscography(data);
    allAlbums.sort((a, b) => a.releaseDate - b.releaseDate);
    console.log(allAlbums);
  }
})
function Album(releaseDate) {
  this.releaseDate = new Date(releaseDate).getTime();
}


function handleDiscography(data) {
  const album = data[0].CreditMediaPairItems;
  return album.map(val => new Album(val.Item.ReleaseDate))
}

function getAlbumData() {
  return $.ajax({
      url: 'https://api-marcalencc-metacritic-v1.p.mashape.com/person/drake/album',
      type: 'get',
      dataType: 'json',
      headers: {
        "X-Mashape-Key": "----------------------------",
        "Accept": "application/json"
      }
    })
    .then(data => handleDiscography)
}


getAlbumData()
  .then(allAlbums => {
    allAlbums.sort(function(a, b) {
      return a.releaseDate - b.releaseDate;
    });

    console.log(allAlbums)
  })