简体   繁体   中英

Error passing arguements between promises in AngularJS

I'm building a promise chain which contains four functions. The purpose of the promise is to make a few API calls. Each API call affects the following one, and some require multiple arguments.

The basic flow of the code below is this:

  1. geocodeLocation is the first function, and takes the $scope.location input which gets geocoded into the result object containing lat , lng , and formattedAddress
  2. getSearchCount is the second function that requires the result from the previous function. This function queries the API using Restangular and returns a plucked_result object.
  3. saveLocation function requires both the result and plucked_result to create a new location, based on whether plucked_result.search_count is less than 1 or not. The search_count variable is returned by this function.
  4. getPhotos requires the result and search_count arguments. Using these it builds a an API request URL that gets fired off. When the response comes back, the photos are saved to the db.

The error occurs within the saveLocation function. The error being returned is:

TypeError: Cannot read property 'search_count' of undefined

Here's the code (with a few comments on what's going on):

var geocodeLocation, getPhotos, getSearchCount, saveLocation;
// geocode the $scope.location into a formatted address with latitude and longitude
geocodeLocation = function(location) {
  return Geocoder.geocodeAddress(location).then(function(result) {
    $scope.geocodingResult = "(lat, lng) " + result.lat + ", " + result.lng + " (address: '" + result.formattedAddress + "')";
    console.log(result);
    // pass the result object from the previous function into the next function
    return result;
  });
};

getSearchCount = function(result) {
  // fetch the locations from the API (using Restangular)
  return Global.locationsRoute().getList().then(function(data) {
    var plucked_result;
    // use underscore's _findWhere to pluck out the location we're looking for, and extract it's search_count
    plucked_result = _.findWhere(data, {
      name: result.formattedAddress
    });
    // this is logging correctly
    console.log(plucked_result);
    return plucked_result;
  });
};

saveLocation = function(plucked_result, result) {
  var newLocation, search_count;
  // this is logging incorrectly, and is where the error occurs
  search_count = plucked_result.search_count;
  console.log(search_count);
  // if the search_count is more than 1, increment and update the search_count
  if (!(search_count < 1)) {
    plucked_result.search_count = search_count + 1;
  } else {
  // if the search_count is less than 1, create a new location
    newLocation = {
      name: result.formattedAddress,
      lat: result.lat,
      lng: result.lng,
      search_count: 1
    };
    Global.locationsRoute().post(newLocation);
  }
  return search_count;
};

// this function requires both the result and search count to build the 500px API request string
getPhotos = function(result, search_count) {
  var newUrl, url;
  url = Global.externalAPI() + "search?geo=" + result.lat + "," + result.lng + ",25km&rpp=5&image_size=4&tags=true&sort=votes_count&only=[Landscapes][City+%26+Architecture][Nature][Urban+Exploration][Underwater][Travel][Journalism][Black+and+White]&page=" + search_count + "&consumer_key=" + Global.consumerKey();
  newUrl = Restangular.oneUrl('500px', url).get();
  return newUrl.then(function(data) {
    var newPhoto, photo, _i, _len, _ref, _results;
    $scope.photos = data;
    _ref = data.photos;
    _results = [];
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      photo = _ref[_i];
      newPhoto = {
        name: photo.name,
        description: photo.description,
        image_url: photo.image_url,
        search_term: result.formattedAddress
      };
      _results.push(Global.photosRoute().post(newPhoto));
    }
    return _results;
  });
};

$scope.geocode = function() {
  var location;
  if ($scope.location) {
    location = $scope.location;
    return geocodeLocation(location).then(getSearchCount).then(saveLocation).then(getPhotos);
  }
};

The question here is: how do I pass the result , plucked_result and search_count variables between all the functions?

Solved. Promises can't pass more than one argument between them, so you need to bundle all of your objects and variables into an array, and pass that array between the functions. For example:

var getSearchCount, saveLocation;

getSearchCount = function(result) {
  return Global.locationsRoute().getList().then(function(data) {
    var passed_data, plucked_result;
    plucked_result = _.findWhere(data, {
      name: result.formattedAddress
    });
    passed_data = [result, plucked_result];
    return passed_data;
  });
};

saveLocation = function(passed_data) {
  var newLocation, plucked_result, result, search_count;
  result = passed_data[0];
  plucked_result = passed_data[1];
  search_count = plucked_result.search_count;
  if (!(search_count < 1)) {
    plucked_result.search_count = search_count + 1;
    plucked_result.put();
  } else {
    newLocation = {
      name: result.formattedAddress,
      lat: result.lat,
      lng: result.lng,
      search_count: 1
    };
    Global.locationsRoute().post(newLocation);
  }
  passed_data = [result, search_count];
  return passed_data;
};

Where passed_data is an array containing the objects and variables.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM