AngularJS factory with a call to $ http should I care about the readiness of the response?

I have a similar factory with a call to $ http inside, as shown below:

appModule = angular.module('appModule', []); appModule.factory('Search', function($rootScope, $http) { var Search; Search = {}; Search.types: ["bacon"]; Search.pastEvents = null; $http.get('api/highlights').success(function(response) { return Search.pastEvents = response.data; }); return Search; }); var notes_module = angular.module('notes', []); notes_module.config(['$routeProvider', function ($routeProvider) { var notes_promise = ['Notes', '$route', 'Search', function (Notes, $route, Search) { //suspect that Search not having pastEvents ready in time of calling index method //Notes resource return Notes.index({subject_id: 1 }, Search); }]; $routeProvider.when('/notes', { templateUrl:'index.tpl.html', controller:'NotesCtrl', resolve:{ notes: notes_promise, } }); }]); 

Should I take care when the data from the $ http call is ready and when this factory is initialized / entered? Will it be ready? If I have to take care of how I do it?

I suspect that the Search object does not have pastEvents ready when calling the Notes resource index method.

+4
source share
1 answer

It depends:

If you immediately put in $scope to be used, for example. in ng-repeat , then no.

If you need another function in your controller, then yes. For instance. if you use your pastEvents in the filter function on your controller. In this case, it is best to keep all the manipulations inside and use $q to solve the asynchronous puzzle.

(This is just an example)

 appModule.factory('sharedApplication', function($rootScope, $http, $q) { var deferred = $q.defer(); $rootScope.$on('data:loaded', function(e, data) { deferred.resolve(data); }); return { getApp: function(filter) { if (!filter) { filter = function() { return true; } } var filtered = {}; deferred.promise.then(function(data) { filtered.pastEvents = _.filter(data, filter); }; return filtered; } }; }); 

A little explanation. The data comes from an event in the service. At the moment, getApp() could already be called. But that doesn’t matter, because $q will make sure that the data is filtered out only after it arrives. The controller should not know that, while it is not trying to do such things as:

 $scope.app = service.getApp(); for(var i = 0; i < $scope.app.pastEvents.length; i++) { ... } 

If you really need to evaluate the content in the controller, use $scope.$watch() , for example:

 $scope.$watch('app', function(value) { ... }, true); 

Edit:

In my opinion, Search is not yet allowed in your situation when you use it in your $routeProvider :

 Notes.index({subject_id: 1 }, Search) 

Therefore, try enabling Search and use the Notes resource in your controller.

You need to return the promise to the Search service. Two options:

  • return the promise of $ http, but this is probably not what you want if you need to do something with the data first
  • use $ q and return the promise

Example $ q:

 appModule.factory('Search', function($rootScope, $http, $q) { var deferred = $q.defer(); $http.get('api/highlights').success(function(response) { deferred.resolve({ type: ["bacon"], pastEvents: response.data)}; }); return deferred.promise; }); 
+5
source

All Articles