0
Map.prototype.updateMap = function (vehicles) {
    nextVehicle:
    for (var i = 0; i < vehicles.length; i++) {
        for (var j = 0; j < this.oldVehicles.length; j++) {
            var vehicle = vehicles[i];
            var oldVehicle = this.oldVehicles[j];

            if (vehicle.registration == oldVehicle.registration) {
                oldVehicle.getPosition(function(latLng) {
                    if (vehicle.latitude != oldVehicle.lat) {
                        var newPos = new plugin.google.maps.LatLng(vehicle.latitude, vehicle.longitude);
                        oldVehicle.setPosition(newPos);
                    }

                    continue nextVehicle;
                });
            }
        }
    }
};

The code above does not work. I have a feeling this is to do with scope, I can't reach the nextVehicle label from inside the oldVehicle.getPosition method. How can I get around this?

jskidd3
  • 4,609
  • 15
  • 63
  • 127
  • @TravisJ Oh? Please explain? – jskidd3 May 23 '14 at 19:47
  • Sorry, misread it at first. – Travis J May 23 '14 at 19:48
  • Why do you need to do a continue nextVehicle? Also is getPosition async? – Brian Mains May 23 '14 at 19:50
  • @BrianMains I need to continue because a match has been made (the for loops are trying to find a match). As for the getPosition method, I am unsure, is there a way I can test this? – jskidd3 May 23 '14 at 19:51
  • 1
    callbacks usually indicate async, and are not guaranteed to be called when you expect, so yes it would be executing outside of that scope. As the entire for loop could have processed before the callback is ever called and there is nothing to continue anyway. – Brian Mains May 23 '14 at 19:53
  • @Quentin, how can you mark this as a duplicate if I haven't yet confirmed the function is asynchronous or not? – jskidd3 May 23 '14 at 19:54

2 Answers2

1

Separate the matching logic from the update logic.

Map.prototype.updateMap = function (vehicles) {
    // Only need to look up array lengths once
    var vehiclesLength = vehicles.length,
        oldVehiclesLength = this.oldVehicles.length; 

    for (var i = 0; i < vehiclesLength; i++) {
        var vehicle = vehicles[i];
        var oldVehicle = null;

        // Find oldVehicle
        for (var j = 0; j < oldVehiclesLength; j++) {

            if (vehicle.registration == oldVehicle[j].registration) {
                oldVehicle = oldVehicles[j];
                break;
            }
        }

        // Check for update if found
        if (oldVehicle){

            // Create closure for async callbacks
            (function(oldV, lat,lng){

                oldV.getPosition(function(latLng) {
                   if (lat != oldV.lat) {
                       var newPos = new plugin.google.maps.LatLng(lat,lng); 
                        oldV.setPosition(newPos);
                   }

                });

             })(oldVehicle, vehicle.latitude, vehicle.longitude);
        }
    }
};
Malk
  • 11,855
  • 4
  • 33
  • 32
0

Just move the continue nextVehicle; line from inside the callback to immediately following the call to oldVehicle.getPosition(...):

Map.prototype.updateMap = function (vehicles) {
    nextVehicle:
    for (var i = 0; i < vehicles.length; i++) {
        for (var j = 0; j < this.oldVehicles.length; j++) {
            var vehicle = vehicles[i];
            var oldVehicle = this.oldVehicles[j];

            if (vehicle.registration == oldVehicle.registration) {
                oldVehicle.getPosition(function(latLng) {
                    if (vehicle.latitude != oldVehicle.lat) {
                        var newPos = new plugin.google.maps.LatLng(vehicle.latitude, vehicle.longitude);
                        oldVehicle.setPosition(newPos);
                    }
                });

                continue nextVehicle;
            }
        }
    }
};

This assumes the call to getPosition is a synchronous operation.

Edit:

Now if getPosition is asynchronous, you will need to use an asynchronous loop:

Something along this line might do the trick:

Map.prototype.updateMap = function (vehicles) {
    var i = 0, j = -1, self = this;

    var updatePosition = function() {
        j++;

        if (j == self.oldVehicles.length) {
            j = 0;
            i++;
        }

        if (i === vehicles.length) {
            return; // We're done
        }

        var vehicle = vehicles[i];
        var oldVehicle = self.oldVehicles[j];

        if (vehicle.registration !== oldVehicle.registration) {
            updatePosition();
        }
        else {
            oldVehicle.getPosition(function(latLng) {
                if (vehicle.latitude != oldVehicle.lat) {
                    var newPos = new plugin.google.maps.LatLng(vehicle.latitude, vehicle.longitude);
                    oldVehicle.setPosition(newPos);
                    updatePosition();
                }
            });
        }
    };

    updatePosition();
};
Greg Burghardt
  • 17,900
  • 9
  • 49
  • 92
  • I now know that `getPosition` is not a synchronous operation, and also this wouldn't work as iterating with continue should only be done if `vehicle.latitude` is not equal to `oldVehicle.lat` (as executed in the if statement inside the asynchronous callback). – jskidd3 May 23 '14 at 20:14
  • I just amended my answer to give you an idea how you can create an asynchronous loop. – Greg Burghardt May 23 '14 at 20:19