2016-10-05 73 views
0

我面临一个问题,即控制器调用服务函数getMyList,但myLists尚未填充,因为$ http调用需要一些时间才能完成。

如何解决此问题?

这里是我的代码片段:

服务

app.factory('myService', function($http) { 
    var myList = []; 

    $http.get("http://myService/json.data").then(function (resp) { 
     myLists = resp.data; 
    }); 

    return { 
     getMyList: function (name) { 
      for (var i = 0; i < myLists.length; i++) { 
       if (myList[i].name == name) { 
        return myLists[i]; 
       } 
      } 
     } 
    } 
} 

控制器:

app.controller('MainCtrl', function(myService,$scope) { 
    var testName = "test" 
    myService.getMyList(testName).then(function(resp) { 
     // do something with resp data 
    }); 
}); 
+0

你有什么路由器?他们哪一个? – Hitmands

+0

我没有路由器。但是从控制器中,我需要调用myService.getMyList,它返回从缓存myLists – SimpleCoder

回答

2

首先需要解决的错别字,并选择更好的命名。然后,你需要返回元素的一个承诺,而不是一个元素(这是控制器期望什么,顺便说一句):

app.factory('myService', function($http) { 
    // this defines a promise which, when resolved, contains an array of elements 
    var listPromise = $http.get("http://myService/json.data").then(function(resp) { 
     return resp.data; 
    }); 

    return { 
     // this returns a promise which, when resolved, contains the element with the given name 
     getElementFromList: function(name) { 
      return listPromise.then(function(list) { 
       return list.filter(function(element) { 
        return element.name === name; 
       })[0]; 
      }); 
     } 
    }; 
}); 
+0

好的列表。这是我最初的问题最接近的答案。当我调用myService.getElementFromList(testName).then(function(resp)){//做点什么}时,我仍然在我的控制器类中得到了resp undefined – SimpleCoder

+0

然后你可能在列表中没有任何具有该名称的元素。调试时会发生什么? –

0

每一个HTTP调用返回角一个promise,所以在您的服务仅返回HTTP调用并返回promise

然后在你的控制器,你可以使用thenerror回调处理来自serviceapi调用的响应。

厂:

app.factory('myService', function($http) { 
    var myList = []; 
    return { 
     getMyList: function (name) { 
      $http.get("http://myService/json.data") 
     } 
    } 
} 

控制器:

app.controller('MainCtrl', function(myService,$scope) { 
    var testName = "test" 
    myService.getMyList() 
    .then(function successCallback(resp) // Success call back 
    { 
      if(resp.data) 
      { 
      myLists = resp.data; 
      for (var i = 0; i < myLists.length; i++) { 
       if (myList[i].name == testName) { // you can use your testName here itself. 
        return myLists[i]; 
       } 
      } 

      } 
    }, 
    function errorCallback(resp) // Error call back 
    { 
     console.log(resp) 
    }); 
}); 
0

如果您使用的是一些客户端侧路由器实现:看看Route.Resolve两个Ui.RouterngRoute实施。

如果您没有任何路由器,那么您可以做一些小技巧...只需从您的工厂返回一个对象引用,并在出现分辨率时使用期望值填充该对象:

angular 
 
    .module('test', []) 
 
    .constant('API', 'https://jsonplaceholder.typicode.com') 
 
    .factory("PostResolved", function($http, API) { 
 
    var result = []; 
 
    $http 
 
     .get(API + '/posts/1') 
 
     .then(function(response) { 
 
     result.push(response.data); 
 
     }) 
 
    ; 
 
    
 
    return result; 
 
    }) 
 

 
    .controller('TestCtrl', function($scope, PostResolved) { 
 
    $scope.posts = PostResolved; 
 
    }) 
 
;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 

 
<section ng-app="test"> 
 
<article ng-controller="TestCtrl"> 
 
    <div ng-repeat="post in posts"> 
 
    <h1 ng-bind="post.title"></h1> 
 
    </div> 
 
</article> 
 
</section>

0

为什么不使用类似如下:

app.factory('myService', function($http) { 
 
    return { 
 
     getMyList: function (name) { 
 
      var myList = []; 
 
      $http.get("http://myService/json.data").then(function (resp) { 
 
       myLists = resp.data; 
 
      }); 
 
      
 
      scope.$evalAsync(function() { 
 
       for (var i = 0; i < myLists.length; i++) { 
 
        if (myList[i].name == name) { 
 
         return myLists[i]; 
 
        } 
 
       } 
 
      }); 
 
     } 
 
    } 
 
}

+0

关键是我想调用getMyList方法之外的$ http.get。我需要以某种方式缓存http调用的结果。不确定当我没有将结果存储在作用域中时,$ evalAsync会执行 – SimpleCoder

+0

我看到,让我们尝试使用$ evalAsync来包装myLists = resp.data;那么,希望可以帮助 – Kerisnarendra

0

我设法解决这个通过使用$超时。任何有更好建议的人都会让我知道。我不能让范围。$ evalAsync工作

服务

app.factory('myService', function($http, $timeout) { 
    var lists = []; 

    $http.get("http://myService/json.data").then(function (resp) { 
     lists = resp.data; 
    }); 

    return { 
     getMyList: function (name) { 
      return $timeout(function() { 
       for (var i = 0; i < lists.length; i++) { 
        if (lists[i].name == name) { 
         return lists[i]; 
        } 
       } 
     }, 2000) 

    } 
} 

控制器

app.controller('MainCtrl', function(myService,$scope) { 
    var testName = "test" 
    myService.getMyList(testName).then(function(resp) { 
     // do something with resp data 
    }); 
}); 
+0

这是错误的答案。你的http响应在2秒之前发生,这就是为什么它的工作原理,如果需要更多时间。 – ram1993

+0

是的,我知道。我愿意接受建议和改进 – SimpleCoder

+0

我已经创建了[笔](https://codepen.io/anon/pen/KgQgKk?editors=1011),与您的代码类似。我相信JBNizet已经给出了正确的答案。另一个解决方案是$ q。但没有必要。就像在这两种情况下你会回到承诺。 – ram1993