jQuery排序功能无法正常工作

时间:2021-12-14 21:28:13

Based on the user location and a store location I try to figure out what the distance is between this two. This is working, but what I want is an array with all the values and sort on the distance between the two points.

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

I have my add_stores_to_array function, wich add all stores to the array stores when it is looping through the JSON file.

我有我的add_stores_to_array函数,它在循环遍历JSON文件时将所有商店添加到数组商店。

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);

    });
};

After the $.each I call the sort function. But after logging it to the console, it is still not sorted.

在$ .each之后我调用了sort函数。但在将其记录到控制台后,它仍然没有排序。

My sort_stores function:

我的sort_stores函数:

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

First I thought it wasn't working because the $.each was still running, but after adding this code, it still doesn't working:

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

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

So, I tried something different. I call the sort_stores(stores) function in the $.each.

所以,我尝试了不同的东西。我在$ .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);
    }
});

And it works.. the array is sorted based on the value distance in the array. But now he sorts the array after each added store.. not really effective.

它的工作原理..数组根据数组中的值距离进行排序。但是现在他在每个添加商店之后对阵列进行排序......不是很有效。

Is there a proper way to call the sort_stores(stores) function one time, and sort it when all stores are added to the array?

是否有一种正确的方法可以调用sort_stores(stores)函数一次,并在将所有商店添加到数组时对其进行排序?

EDIT:

If I place an alert() before the sort_stores(stores) it is working..

如果我在sort_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);
    });
};

Edit 2:

Normally I call the function add_stores_to_array from here?

通常我从这里调用函数add_stores_to_array?

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

1 个解决方案

#1


1  

There's nothing wrong with your sort function. The problem is that directionsService.route is asynchronous call and the rest of the code will run even when all the calls are not completed yet.

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

You can use jQuery.when(). Here is the new add_stores_to_array() function

你可以使用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);
        });
    });
};

EDIT

Here is another approach. Since you need to wait until all responses are returned, you can customize your sort function to check for the response count. If it's equal to total (which means all calls have finished successfully) then sort the array.

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

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

Then change the add_stores_to_array function as follows.

然后更改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
                }
            });
        });
    });
};

#1


1  

There's nothing wrong with your sort function. The problem is that directionsService.route is asynchronous call and the rest of the code will run even when all the calls are not completed yet.

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

You can use jQuery.when(). Here is the new add_stores_to_array() function

你可以使用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);
        });
    });
};

EDIT

Here is another approach. Since you need to wait until all responses are returned, you can customize your sort function to check for the response count. If it's equal to total (which means all calls have finished successfully) then sort the array.

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

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

Then change the add_stores_to_array function as follows.

然后更改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
                }
            });
        });
    });
};