2016-11-11 6 views
1

Основываясь на местоположении пользователя и местоположении магазина, я пытаюсь выяснить, какое расстояние между этими двумя. Это работает, но то, что я хочу, это массив со всеми значениями и сортировка на расстоянии между двумя точками.Функция сортировки jQuery не работает должным образом

У меня есть моя функция add_stores_to_array, которая добавляет все магазины в массив stores, когда он перебирает файл 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); 

    }); 
}; 

После $.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); 
} 

Итак, я попробовал что-то другое. Я вызываю функцию sort_stores(stores) в $.each.

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) один раз и отсортировать ее, когда все магазины добавляются в массив?

EDIT:

Если я размещаю alert() перед sort_stores(stores) она работает ..

   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:

Обычно я вызываю функцию add_stores_to_array отсюда?

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

try 'a.distance> b.distance? 1: a.distance Rajesh

+0

Hm, похоже, функция 'stores.sort (function (a, b)' даже не работает, если я поместил ее после '$ .each'? Если я поместил' alert() ' внутри функции 'stores.sort (функция (a, b)' nothings happend? –

+0

вы проверили консоль на наличие ошибок? edit: ничего не получилось с вашей функцией сортировки. После того, как вы получите функцию, она будет работать соответственно. –

ответ

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

EDIT

Вот другой подход. Поскольку вам нужно подождать, пока все ответы будут возвращены, вы можете настроить свою функцию сортировки, чтобы проверить количество ответов. Если он равен сумме (что означает, что все вызовы завершены успешно), сортируйте массив.

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 
       } 
      }); 
     }); 
    }); 
}; 
+0

Я могу вызвать 'add_stores_to_array(). Done (function() {' в любом месте, из-за '.done()', правильно? –

+0

да, но мне нужно немного изменить код, он, похоже, не работает –

+0

А, ок, спасибо. Я буду ждать! –

Смежные вопросы