【问题标题】:jQuery sort function not working properlyjQuery排序功能无法正常工作
【发布时间】:2016-11-11 09:38:04
【问题描述】:

根据用户位置和商店位置,我试图找出这两者之间的距离。这是可行的,但我想要的是一个包含所有值的数组,并对两点之间的距离进行排序。

我有我的 add_stores_to_array 函数,当它循环通过 JSON 文件时,它将所有存储添加到数组 stores

add_stores_to_array = function(position) {
    var user_latitude = position.coords.latitude;
    var user_longitude = position.coords.longitude;

    $.getJSON('/stores').done(function(data) {

        $.each(data.features, function(i, item) {
            var store_latitude = item.geometry.coordinates[1];
            var store_longitude = item.geometry.coordinates[0];

            var user = new google.maps.LatLng(user_latitude, user_longitude);
            var store = new google.maps.LatLng(store_latitude, store_longitude);

            var directionsService = new google.maps.DirectionsService();

            var request = {
                origin:user,
                destination:store,
                travelMode: google.maps.DirectionsTravelMode.DRIVING
            };

            directionsService.route(request, function(response, status) {
                if (status == google.maps.DirectionsStatus.OK) {
                    var response = Math.ceil(response.routes[0].legs[0].distance.value / 1000);

                    // add distance and store id to the array stores
                    stores.push({distance: response, id: item.properties.Nid});
                }
            });
        });

        // call the sort function
        sort_stores(stores);

        console.log(stores);

    });
};

$.each 之后我调用排序函数。但是登录到控制台后,还是没有排序。

我的sort_stores 功能:

sort_stores = function(stores){
    stores.sort(function(a, b){
        return a.distance - b.distance;
    });
};

首先我认为它不起作用,因为 $.each 仍在运行,但添加此代码后,它仍然不起作用:

if (i == Object.keys(data.features).pop()) {
    sort_stores(stores);
}   

所以,我尝试了一些不同的方法。我在$.each 中调用了sort_stores(stores) 函数。

directionsService.route(request, function(response, status) {
    if (status == google.maps.DirectionsStatus.OK) {
        var response = Math.ceil(response.routes[0].legs[0].distance.value / 1000);

        stores.push({distance: response, id: item.properties.Nid});
        sort_stores(stores);
    }
});

它可以工作.. 数组是根据数组中的值距离排序的。但是现在他在每次添加商店后对数组进行排序.. 并不是很有效。

有没有合适的方法调用sort_stores(stores)函数一次,并在所有商店都添加到数组时对其进行排序?

编辑:

如果我在sort_stores(stores) 之前放置一个alert(),它就可以工作..

                if (status == google.maps.DirectionsStatus.OK) {
                    var response = Math.ceil(response.routes[0].legs[0].distance.value / 1000);

                    stores.push({distance: response, id: item.properties.Nid});
                }
            });
        });

        alert('Call the sort_stores(stores) function after the $.each, with an alert.. it is working?');
        sort_stores(stores);
    });
};

编辑 2:

通常我从这里调用函数add_stores_to_array

get_user_location = function(){
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(add_stores_to_array);
    }
};

【问题讨论】:

  • 试试a.distance > b.distance ? 1 : a.distance < b.distance ? -1 : 0
  • 嗯,如果我把它放在$.each 之后,看起来函数stores.sort(function(a, b) 甚至都没有运行?如果我在stores.sort(function(a, b) 内放置一个alert() 什么都没有发生?
  • 您检查控制台是否有错误?编辑:您的排序功能没有问题。一旦你得到这个功能,它就会相应地工作。
  • 是的,但没有错误。请在我的第一篇文章中查看我的编辑。
  • 它在$.getJSON('/stores').done(function(data) { } 块中,应该在$.each() 之后工作。应该有错误。如果您没有这样做,请检查 chrome。编辑:好的,由于异步调用,看起来像一个竞争条件。

标签: javascript jquery arrays json sorting


【解决方案1】:

您的排序功能没有问题。问题是directionsService.route 是异步调用,即使所有调用尚未完成,其余代码也会运行。

您可以使用jQuery.when()。这是新的add_stores_to_array() 函数

add_stores_to_array = function(position) {
    var promises = []; //ADDED promise array
    var user_latitude = position.coords.latitude;
    var user_longitude = position.coords.longitude;

    $.getJSON('/stores').done(function(data) {
        $.each(data.features, function(i, item) {
            var store_latitude = item.geometry.coordinates[1];
            var store_longitude = item.geometry.coordinates[0];

            var user = new google.maps.LatLng(user_latitude, user_longitude);
            var store = new google.maps.LatLng(store_latitude, store_longitude);

            var directionsService = new google.maps.DirectionsService();

            var request = {
                origin:user,
                destination:store,
                travelMode: google.maps.DirectionsTravelMode.DRIVING
            };

            var dfd = directionsService.route(request, function(response, status) {
                if (status == google.maps.DirectionsStatus.OK) {
                    var response = Math.ceil(response.routes[0].legs[0].distance.value / 1000);

                    // add distance and store id to the array stores
                    stores.push({distance: response, id: item.properties.Nid});
                }
            });

            promises.push(dfd); //ADDED store each object in array
        });

        //Now you can do the following without having any async issue.
        $.when.apply(null, promises).done(function() { 
           /* sort & do stuff here */ 
           sort_stores(stores);
           console.log(stores);
        });
    });
};

编辑

这是另一种方法。由于您需要等到所有响应都返回,您可以自定义排序函数来检查响应计数。如果等于 total(这意味着所有调用都已成功完成),则对数组进行排序。

sort_stores = function(stores, responseCount, totalCount ) {
    if (responseCount == totalCount) {
        stores.sort(function(a, b){
            return a.distance - b.distance;
        });
    }
};

然后将add_stores_to_array函数改成如下。

add_stores_to_array = function(position) {
    var user_latitude = position.coords.latitude;
    var user_longitude = position.coords.longitude;

    $.getJSON('/stores').done(function(data) {
        var totalCount = data.features.length; //ADDED Get total count
        var responseCount = 0; //ADDED
        $.each(data.features, function(i, item) {
            var store_latitude = item.geometry.coordinates[1];
            var store_longitude = item.geometry.coordinates[0];

            var user = new google.maps.LatLng(user_latitude, user_longitude);
            var store = new google.maps.LatLng(store_latitude, store_longitude);

            var directionsService = new google.maps.DirectionsService();

            var request = {
                origin:user,
                destination:store,
                travelMode: google.maps.DirectionsTravelMode.DRIVING
            };

            directionsService.route(request, function(response, status) {
                if (status == google.maps.DirectionsStatus.OK) {
                    var response = Math.ceil(response.routes[0].legs[0].distance.value / 1000);

                    // add distance and store id to the array stores
                    stores.push({distance: response, id: item.properties.Nid});
                    responseCount++; //ADDED
                    sort_stores(stores, responseCount, totalCount); //ADDED Call sort function here
                }
            });
        });
    });
};

【讨论】:

  • 我可以在任何地方拨打add_stores_to_array().done(function() {,因为.done(),对吧?
  • 是的,但我需要稍微更改一下代码,它似乎不起作用。
  • $.when.apply(null, add_stores_to_array()).done(function() { 我应该从哪里调用这个函数?请参阅我的第一篇文章,请编辑 2。
  • 好的,你能不能在stores.push({distance: response, id: item.properties.Nid});后面加console.log("store pushed")all done 还是最后一条消息吗?
  • 我已经更新了答案。可以试试第二种方法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-12
  • 2017-08-05
  • 2012-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多