Search code examples
javascriptasynchronousleafletleaflet-routing-machine

leaflet routing, shortest route with multiple origin


I'm kinda new to javascript and I ran into an issue on the website I'm building. A little context: I have a leaflet map, on that map there are multiple vehicles. When I put a new marker on the map, the system has to calculate all routes between that marker and the 30ish vehicles I already have. Then it has to take that array of routes and sort it by shortest distance. I took a brief look at promises, but never managed to get it to work properly.

var get_all_routes = function(){
var promise = new Promise(function(resolve,reject){
var rutas = [];
for(var i = 0;i<Object.keys(puntos).length;i++){  
  get_route(ambulance[i]).then(function(response){
  rutas.push(response);
});
}
resolve(rutas);
});
return promise;
}

ambulance is a global array with the location of every vehicle on the map.

function get_route(punto){
 return new Promise(function(resolve,reject){
 var waypoints = [
  L.Routing.waypoint(L.latLng(feature.getLatLng().lat, feature.getLatLng().lng)),
  L.Routing.waypoint(L.latLng(punto.getLatLng().lat,punto.getLatLng().lng)),
  ];
  var router = new L.routing.osrmv1({});
  router.route(waypoints, function(error, routes) {
  if(error==null){
        resolve(routes[0]);
  }else
    resolve('No route available');
  }, null, {}); 
 });
}

feature is the newly marker placed on the map.

var sort_cars = function(rutas) {
  var promise = new Promise(function(resolve,reject){
    rutas.sort(function(a, b){return a.summary.totalDistance-
    b.summary.totalDistance});
    resolve(rutas);
 });
  return promise;
}

Sorting based on total distance.

And this is how I call this:

get_all_routes().then(function(resolve){
    window.setTimeout(function() {sort_cars(resolve).then(function(resolve){
      routes = resolve;
      other_func()
      .then(other_func2(routes));
    })}, 3000);
});

other_func() and other_func2() do non important stuff. This is working, until it doesn't. Because of the timeout of 3s, if the routing agent takes more than that to get all the routes then all hell breaks loose.

What I need is for the sort_cars() function to wait until all routes are ready in order to do it's thing. Please help!


Solution

  • I ended up doing some more research, and found this tutorial:

    http://jingding.blogspot.cl/2012/05/jquery-deferred-objects-promise.html

    And changed my code to:

    var get_all_routes2=function(){
       var rutas = [];
       mymap.spin(true);
       mymap._handlers.forEach(function(handler) {
        handler.disable();
       });
       var currentStep = get_route2(ambulancias[0].id_recurso,ambulancias[0],puntos[0].tipos_estados.alias2,puntos[0].disponible,puntos[0].servicio,0,rutas);
       for(var i = 1;i<Object.keys(puntos).length;i++){
        currentStep = currentStep.then(function(j){            
            return get_route2(ambulancias[j+1].id_recurso,ambulancias[j+1],puntos[j+1].tipos_estados.alias2,puntos[j+1].disponible,puntos[j+1].servicio,j+1,rutas);
         });
       }
    
        currentStep.done(function(){
          Promise.resolve(sort_cars2(rutas)).then(function(resolve){
          remove_ambulances();
          create_ambulances(resolve);
          mymap.spin(false);
          mymap._handlers.forEach(function(handler) {
              handler.enable();
    
          });
        });
      });
    }
    
    function get_route2(id,punto,alias2,disponibilidad,servicio,i,rutas){
       var defer = $.Deferred();
       var waypoints = [
         L.Routing.waypoint(L.latLng(feature.getLatLng().lat, feature.getLatLng().lng)),L.Routing.waypoint(L.latLng(punto.getLatLng().lat,punto.getLatLng().lng)),
       ];
       var router = new L.routing.osrmv1({});
       router.route(waypoints, function(error, routes) {
         if(error==null){
               rutas.push(routes[0]);
               defer.resolve(i);
         }
       }, null, {});
       return defer.promise();
    }
    
    var sort_cars2 = function(rutas) {
      var promise = new Promise(function(resolve,reject){
        rutas.sort(function(a, b){return a.summary.totalDistance-b.summary.totalDistance});
        resolve(rutas);
      });
      return promise;
    }
    

    Then, I just call it using:

    get_all_routes2();