在不使用同步Ajax的情况下使数据按顺序排列
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在不使用同步Ajax的情况下使数据按顺序排列相关的知识,希望对你有一定的参考价值。
很多时候要根据一个数组获取一组数据,但是Ajax异步导致获取数据的顺序是乱的。
最简单的方法当然是在数据里加上它的编号,然后直接根据数组的顺序添加数据,但这也意味着要根据数据中的编号遍历数组来找到每次得到的数组的index,然后根据此index添加数据。
想要异步获取数据又保证数据的顺序,显然不能用push。
而forEach等数组遍历的callback的第二个参数是index,这样就可以用数组索引的方式来确保顺序。
data.musics.forEach(function (songid, index) { $http({ url: myConstant.sqlUrl + "/songinfo/" + songid + "?time=" +(+new Date()), method: "GET", withCredentials: true }).success(function (data) { $scope.currentList.songs[index] = data.data; }); });
这个代码其实是不安全的。
第一,在ES5或者更老版本里,由于forEach循环很快结束,而数据获取却要慢得多,所以会出现所有数据都放到了最后一个index上互相覆盖。
这里可以用闭包解决:
data.musics.forEach(function (songid, index) {
(function(_index){ $http({
url: myConstant.sqlUrl + "/songinfo/" + songid + "?time=" +(+new Date()), method: "GET", withCredentials: true }).success(function (data) { $scope.currentList.songs[_index] = data.data; });
})(index);
});
问题还没有完
第二,如果快速多次获取数据,在第一次数据还没有获取完成的时候进行第二次获取,则第一次的回调函数在第二次获取数据的时候执行,就会导致第一次的数据掺杂进第二次的数据。
这就需要一个标记量来标记此时此刻获取的数据,是否应该被添加。
我选择用时间戳:
let $scope.time = +new Date();
getData($scope.time);
// 此时传入的数据必须是简单数据形式,否则会被解释为指针,内部获得的数据并不能保持不变.
// 还是那句话,不论是闭包还是函数,如果想要传入的参数不变,就要避免将其指针暴露在外部.
// ES6解决了变量作用域带来的数据混乱,但JS的参数传递形式还是一样的,指针的暴露依然会带来危险.
function getData(time){
data.musics.forEach(function (songid, index) {
(function(_index){
$http({
url: myConstant.sqlUrl + "/songinfo/" + songid + "?time=" +(+new Date()), method: "GET", withCredentials: true }).success(function (data) {
if ($scope.time == time) {
$scope.currentList.songs[_index] = data.data;
}
});
})(index);
});
}
以上是关于在不使用同步Ajax的情况下使数据按顺序排列的主要内容,如果未能解决你的问题,请参考以下文章