Search code examples
javascriptjqueryobject-literal.when

Using jquery.when in an object literal


I've got a javascript/jQuery function called addLocation, which is a method of an object literal:

addLocation: function(latLng, address=false, elevation=false, pan=false)
{

    $.when(geographic.getAddress(latLng), geographic.getElevation(latLng), geographic.getMagneticDeclination(latLng))
        .done(function(data){

            if (data.status != 'OK') {
                window.alert(data.message);
            }

            if (pan) {
                flyityourself.map.panTo(latLng);
                flyityourself.map.setZoom(16);
            }

            flyityourself.addWaypoint(latLng, data);

            flyityourself.addMarker(latLng, data);
        })
        .fail(function(msg) {
            window.alert(msg);
        }
    );
},

The three functions getAddress, getElevation and getMagneticDeclination are all methods of a second object literal named 'geographic'.

But the code is failing.

In the debugger, I have checked all four functions.

  • Each of getAddress, getElevation and getMagneticDeclination create $.Deferred objects and return $.Deferred.promise objects as they should.
  • Each of getAddress, getElevation and getMagneticDeclination are retrieving the right data and are all reaching their respective resolve() statements.
  • But in addLocation(), the data parameter only contains the data returned from getAddress.

Previously, only the three methods getAddress, getElevation and getMagneticDeclination were in the object literal 'geographic'. addLocation was in a flat .js file. In this case the code worked.

But since changing my code to put addLocation inside an object literal, the code has started to fail.

Does $.when work differently in object literals or have I forgotten to qualify something?

Regards. Chris B.


Solution

  • A. Wolff is right in the comment they made - you need 3 params in your done callback, one for each promise handled by when.

    Here's a simple example, supplying a mock geographic object to make your code work in a stand-alone fiddle:

    https://jsfiddle.net/tmLrn4gc/1/

    // Mock geographic object for testing
    geographic = {
      // Return a promise, and a second later, resolve that promise with some
      // dummy data.
      getAddress: function() {
        var dfd = $.Deferred();
        window.setTimeout(function() {
          dfd.resolve("address:lat1,lng1")
        }, 1000);
        return dfd.promise();
      },
      getElevation: function() {
        var dfd = $.Deferred();
        window.setTimeout(function() {
          dfd.resolve("elevation:meters")
        }, 1000);
        return dfd.promise();
      },
      getMagneticDeclination: function() {
        var dfd = $.Deferred();
        window.setTimeout(function() {
          dfd.resolve("declination:degrees")
        }, 1000);
        return dfd.promise();
      }
    };
    
    // A simplified location manager, showing the 3 promises and a done method.
    // The console output in the fiddle shows the 3 promises are resolved as
    // desired.
    LocationManager = {
      addLocation: function(latLng, address=false, elevation=false, pan=false) {
        $.when(
          geographic.getAddress(latLng),
          geographic.getElevation(latLng),
          geographic.getMagneticDeclination(latLng)
        ).done(function(d1, d2, d3) {
            console.log("Done", d1, d2, d3);
        })
      }
    }
    
    // Make it all happen!
    LocationManager.addLocation();