使用Controller作为服务,工厂的所有示例,使用$scope
,我有点困惑。我有一个简单的ng-if
表达式,它返回未定义,因为要评估的数据还没有准备好:
<div ng-if="ctrl.AlreadyBoughtShoe('ShoeId')"> ... </div>
...
<script>
(function() {
var MyApp = angular.module("MyApp", []);
MyApp.controller("MyAppController", function($http, $timeout, ShoeService) {
var x = this
loadRemoteData();
function loadRemoteData() {
ShoeService.GetShoes().then(function(Shoes){
applyRemoteData(Shoes);
});
}
function applyRemoteData(Shoes) {
x.Shoes = Shoes;
}
// FAILS HERE - Get undefined on the array
x.AlreadyBoughtShoe = function(shoeId) {
for (var i = 0; i < x.Shoes.length; i++) {
// Do stuff
}
}
});
MyApp.service("ShoesService", function($http, $q){
return({
GetShoes: GetShoes
});
function GetShoes() {
var request = $http({
method: "GET",
url: /MyUrl",
cache: false,
headers: $myHeaders
});
return( request.then(handleSuccess, handleError));
}
function handleError( response ) {
if (!angular.isObject(response.data) || !response.data.message) {
return( $q.reject( "An unknown error occurred." ) );
}
return( $q.reject(response.data.message) );
}
function handleSuccess( response ) {
return( response.data );
}
});
})();
</script>
另外,如果它是相关的,在这种特殊情况下它与鞋子无关......并且数据是人物对象,并且没有ng-repeat
继续,所以“鞋子”的ID手动输入。我混淆了我的实际代码以简化这一点,因此我可以理解处理它的最佳方法,但ng-if
需要在数据准备好进行评估后进行评估。
我不确定如何最好地使用这种格式的promises或其他任何我需要的东西,我在网上的某个地方找到了一个例子。
答案 0 :(得分:1)
由于ShoeService
中服务调用的异步性质,这种情况正在发生。由于在解析x.Shoes = Shoes
之前调用了代码,您的错误正在发生,基本上是在undefined
上进行迭代。尝试将您的逻辑移动到服务的then
回调中。例如......
function loadRemoteData() {
ShoeService.GetShoes().then(function(Shoes) {
applyRemoteData(Shoes);
x.AlreadyBoughtShoe = function(shoeId) {
for (var i = 0; i < x.Shoes.length; i++) {
// Do stuff
}
}
});
}
如果您愿意,也可以将其移至applyRemoteData
的末尾。无论哪种方式,您都需要在解决x.Shoes
答案 1 :(得分:0)
你是对的 - 当这段代码运行时,x.Shoes
未定义。变化:
x.AlreadyBoughtShoe = function(shoeId) {
for (var i = 0; i < x.Shoes.length; i++) {
// Do stuff
}
}
为:
x.AlreadyBoughtShoe = function(shoeId) {
for (var i = 0; i < (x.Shoes || []).length; i++) {
// Do stuff
}
}
答案 2 :(得分:0)
您有多种选择。
默认情况下,将ng-if评估为false,直到您收到数据为止。您保留AlreadyBoughtShoe
方法但首先检查是否有数据。如果您没有数据但只是返回false。您不再有错误,当您的承诺得到解决时,您的HTML应该反映出来。
You can delay controller initialization until your promise is resolved.
答案 3 :(得分:0)
也许设置信号量或者simillar可以提供帮助。 Promise在一段时间后进行评估,并在成功调用后将变量设置为true可能会有所帮助。然后将该变量添加到ng-if条件,该条件仅在变量为true时才计算函数,因此返回promise。
将变量设置为和条件,这将在两者都为真时进行评估。
<div ng-if="ctrl.loaded && ctrl.AlreadyBoughtShoe('ShoeId')"> ... </div>
然后在成功时将变量设置为true(由于javascript,默认设置为false)。
function loadRemoteData() {
ShoeService.GetShoes().then(function(Shoes){
x.loaded = true;
applyRemoteData(Shoes);
});
}
这可能会有所帮助。