2013-07-16 20 views
11

我有一個像Angular.js通過從異步服務的數據範圍

app.factory('geolocation', function ($rootScope, cordovaReady) { 
    return { 
     getCurrentPosition: cordovaReady(function (onSuccess, onError, options) { 

      navigator.geolocation.getCurrentPosition(function() { 
       var that = this, 
        args = arguments; 

       if (onSuccess) { 
        $rootScope.$apply(function() { 
         onSuccess.apply(that, args); 
        }); 
       } 
      }, function() { 
       var that = this, 
        args = arguments; 
       if (onError) { 
        $rootScope.$apply(function() { 
         onError.apply(that, args); 
        }); 
       } 
      }, options); 
     }), 
     getCurrentCity: function (onSuccess, onError) { 
      this.getCurrentPosition(function (position) { 
       var geocoder = new google.maps.Geocoder(); 
       geocoder.geocode(options,function (results, status) { 
        var city = address_component.long_name; 
       }); 
      }); 
     } 
    } 
}); 

一個服務,我想從控制器事情做像

function MainCtrl($scope, geolocation) { 
    geolocation.getCurrentCity(function(city){ 
     $scope.city = city; 
    }); 
}; 

的getCurrentPosition正常工作和城市也決定了,但我不知道如何訪問控制器中的城市。

會發生什麼情況?當調用getCurrentCity時,它調用getCurrentPosition來確定gps座標。這個座標是作爲參數傳遞給onSuccess方法的嗎?所以這和我想在getCurrentCity方法中做的完全一樣,但我不知道如何。異步地理編碼器檢索到城市,我想將新數據應用於onSuccess方法。

任何想法?

回答

29

你正在處理的回調和異步請求。所以你應該使用$q服務。只需使用$ rootScope和cordovaReady依賴項將其注入到您的服務中即可。 並添加承諾,你的函數類似這樣的

getCurrentCity: function() { 
    var deferred = $q.defer(); 
    this.getCurrentPosition(function (position) { 
     var geocoder = new google.maps.Geocoder(); 
     geocoder.geocode(options,function (results, status) { 
     var city = address_component.long_name; 
     $rootScope.$apply(function(){ 
      deferred.resolve(city); 
     }); 
     }); 
    }); 
    return deferred.promise; 
} 

而在你的控制器,請執行以下操作來處理的承諾。

function MainCtrl($scope, geolocation) { 
    geolocation.getCurrentCity().then(function(result) { //result === city 
    $scope.city = result; 
    //do whatever you want. This will be executed once city value is available 
    });  
}; 
+0

解決了我的問題,我有一個過濾器導致循環。 –

+0

上述控制器實現將$ scope屬性設置爲承諾的第一種方法在Angular 1.3中不再適用。承諾不再被解包,所以你必須使用第二種方法(在後處理程序中設置$ scope屬性) – jbandi

+0

@jbandi:你似乎認爲某些東西已經改變。我沒有得到確切的變化。你介意給我澄清一下嗎?我會相應地更新答案。 –

4

只需在服務中調用onSuccess方法,而不是在那裏處理結果。

getCurrentCity: function (onSuccess, onError) { 
    this.getCurrentPosition(function (position) { 
     var geocoder = new google.maps.Geocoder(); 
     geocoder.geocode(options, onSuccess); 
    }); 
} 

而在你的控制,分析結果,並指定城市:

function MainCtrl($scope, geolocation) { 
    geolocation.getCurrentCity(function(results, status){ 
     // Parse results for the city - not sure what that object looks like 
     $scope.city = results.city; 
    }); 
}; 
5

試試這個

function MainCtrl($scope, geolocation) { 
    $scope.city = null; 
    geolocation.getCurrentCity(function(city){ 
     $scope.city = city; 
     if(!$scope.$$phase) { 
      $scope.$digest($scope); 
     } 
    }); 
}; 

有時候,守望者並不總是instanciating控制器時,通過強制消化情況下,如果範圍不相叫,你可以去你想去的地方我相信。 如果我不明白你的問題,請告訴我。

哦,我不知道如果我閱讀代碼properrly但似乎你不調用你的函數的onSuccess回調: 本替換你getCurrentCity功能:

getCurrentCity: function (onSuccess, onError) { 
     this.getCurrentPosition(function (position) { 
      var geocoder = new google.maps.Geocoder(); 
      geocoder.geocode(options,function (results, status) { 
       var city = address_component.long_name; 
       if(typeof onSuccess === 'function') { 
        onSuccess(city); 
       } 
      }); 
     }); 
    } 
3

糾正我,如果我錯了,但提出的解決方案將無法完全工作,因爲更新的Angular版本(> 1.2 !?)不再自動解包$ q promise。

這樣:

$scope.city = geolocation.getCurrentCity(); 

將永遠是一個承諾。所以你永遠不得不使用:

geolocation.getCurrentCity().then(function(city) { 
    $scope.city = city; 
}