在 angular 中返回链式承诺的 "last" 值

Returning "last" value of chained promises in angular

我正在尝试进行一些地理定位,并根据坐标调用 RESTful API return 一些数据。然后我要解析这个数据,最后return就可以了 我对 angular.js 和承诺还很陌生,因此这段代码是我在互联网上看到的东西的混合体:D

我已经完成了所有工作,但我错过了最后一步:return将处理后的结果数组 ("allSpots") 发送给原始调用者。我在这里错过了什么?

.factory('wifiSpotFactory', function (WifinderModel, $q, $http) {

            function onGeolocationSuccess(position) {

            var url = 'http://localhost:34915/api/spots?latitude=' + position.coords.longitude + '&longitude=' + position.coords.latitude;

            $http.get(url).then(function (response) {

                var allSpots = [], data = response.data;
                for (var i = 0; i < data.length; i++) {
                    var newSpot = new WifinderModel.wifiSpot(data[i].id, data[i].name, data[i].password, data[i].address);
                    allSpots.push(newSpot);
                }

                return allSpots;

            }, function (error) {
                console.log(error);
            });

        };

            var wifiSpotFactory = {
                loadNearSpots: function() {
                var geo_options = {
                    enableHighAccuracy: true,
                    maximumAge: 50000,
                    timeout: 30000
                };

                var deferred = $q.defer();

                navigator.geolocation.getCurrentPosition(deferred.resolve, deferred.reject, geo_options);

                return deferred.promise
                        .then(onGeolocationSuccess)
                        .then(function(allSpots) { return allSpots; });
            }
            };
            return wifiSpotFactory;
            } )

那么在controller中,如何获取promise的值呢?

.controller('wifiListController', [
                '$scope', 'wifiSpotFactory', function ($scope, wifiSpotFactory) {
                    $scope.spots = wifiSpotFactory.loadNearSpots();
               }
])

Return 链接的承诺:

function onGeolocationSuccess(position) {
  var url = 'http://localhost:34915/api/spots?latitude=' + position.coords.longitude + '&longitude=' + position.coords.latitude;

  return $http.get(url).success(function(data, status, headers, config) {
    var allSpots = [];
    for (var i = 0; i < data.length; i++) {
      var newSpot = new WifinderModel.wifiSpot(data[i].id, data[i].name, data[i].password, data[i].address);
      allSpots.push(newSpot);
    }

    return allSpots;

  }).error(function(data, status, headers, config) {});
};

那么调用可以是:

deferred.promise
.then(onGeolocationSuccess)
.then(function(allSpots) { ... });

Callback 没有 return 数据的能力,你真的应该在那里使用 promise 模式,它能够 return 来自 promise 的数据。您 onGeolocationSuccess 正在使用看似 return data 但实际上并非如此的回调模式。

你可以通过returnonGeolocationSuccess方法的承诺来解决这个问题,为此你需要return$http.get对象,它已经returns 是一个 promise 对象。在该函数的 .then 中,您将得到 data,它从 API 编辑了 return。从 .then 函数你可以 return 一个 data 这将帮助你遵循 promise pattern.

代码

.factory('wifiSpotFactory', function(WifinderModel, $q, $http) {

  function onGeolocationSuccess(position) {
    var url = 'http://localhost:34915/api/spots?latitude=' + position.coords.longitude + '&longitude=' + position.coords.latitude;

    return $http.get(url).
    then(function(response) {
      var allSpots = [],
          data = response.data;
      for (var i = 0; i < data.length; i++) {
        var newSpot = new WifinderModel.wifiSpot(data[i].id, data[i].name, data[i].password, data[i].address);
        allSpots.push(newSpot);
      }
      return allSpots;

    }, function(error) {
      console.log(error)
    });
  };

  var wifiSpotFactory = {
    loadNearSpots: function() {
      //..other code as is..to make solution cleaner removed that part.
      //return promise to follow promise chain
      return deferred.promise
      .then(onGeolocationSuccess)
      .then(function(allSpots) {
        return allSpots;
      });
    }
  };
  return wifiSpotFactory;
})

控制器

.controller('wifiListController', ['$scope', 'wifiSpotFactory', 
   function ($scope, wifiSpotFactory) {
       wifiSpotFactory.loadNearSpots().then(function(data){
           $scope.spots = data; //data will be available inside `.then` which promise resolve/reject
       });
   }
])