This question already has answers here:
Why are Callbacks from Promise `.then` Methods an Anti-Pattern
(2 answers)
Why are AngularJS $http success/error methods deprecated? Removed from v1.6?
(2 answers)
Closed 4 years ago.
I understand the basic Javascripts callbacks, but I do not know what $rootScope.$emit 'dispatchQuery' is doing.
(function() {
angular.module('sp').factory('Object', [
'$rootScope', function($rootScope) {
var Object;
return Object = {
load: function(callback) {
return $http(method: "get", url: "http://myhost/bananas", options = {}).success(function(response) {
$rootScope.myItems = response.items;
return callback && callback();
});
}
};
}
]);
}).call(this);
it is called from main.js
sp.run [
'$rootScope','Object'
, function($rootScope, Object) {
Object.load = function(){ $rootScope.$emit 'Query'}
}]
$rootScope.$emit() dispatches event messages upward through the scope chain. Since $rootScope is at the top of the scope chain, only listeners on $rootScope will receive the event. Somewhere in your code, there should be a $rootScope.$on('Query', function(){...})
However, the syntax of your code seems wrong. The code below will generate a syntax error.
$rootScope.$emit 'Query'
Also, your factory creates a .load() method which is then replaced with a different method in your .run() block. Nowhere in your code sample is either method actually called.
Finally...you should avoid using the keyword Object. Consider giving your service factory a more meaningful name.
Related
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
I have a problem about the scope of variables in a Cordova program.
This is my code:
angular.module('starter.services', [])
.factory('myFactory', function ($http) {
var myVar = "HELLO";
alert(myVar); //HELLO -> Correct
$http.get("URL").then(
function (response) {
myVar = response.data;
alert(myVar) // Correct Answer
}, function (error) {
console.log("Get config.json error - " + JSON.stringify(error));
}
);
alert(serverName); //HELLO -> why?
I declared my variable outside the http block. Can you help me? thanks
For one, you have never defined serverName so that will alert undefined.
Your final Alert is also being called before your $http.get() has returned, so myVar hasn't been updated. I think you should read up on the $http service (https://docs.angularjs.org/api/ng/service/$http) and how promises work (http://andyshora.com/promises-angularjs-explained-as-cartoon.html).
This question already has an answer here:
Unexpected request: GET No more request expected at $httpBackend
(1 answer)
Closed 7 years ago.
I am trying to make a demo of $http request and test that service also..I do like this
.controller('cntrl',function($scope,appfactory,$http){
$scope.data=[];
appfactory.setValue('test abc');
$scope.getData=function(){
$http.get('data.json').success(function(data){
console.log(JSON.stringify(data))
$scope.data=data;
}).error(function(data){
console.log(JSON.stringify(data))
})
}
$scope.getData();
$scope.toggle=function(){
if(appfactory.mode()=='a'){
$scope.message='naveen'
}else {
if(appfactory.mode()=='b'){
$scope.message='parveen'
}
}
}
})
I load that data from json file and display it on view..But when I try to test that application ..I got error why ? how to remove that error
beforeEach(inject(function($rootScope,$controller,appfactory,_$httpBackend_) {
$scope = $rootScope.$new();
$httpBackend=_$httpBackend_;
createController = function() {
return $controller('cntrl', {'$scope' : $scope });
};
}));
it("tracks that the spy was called", function() {
var response=[{"name":"naveen"},{"name":"parveen"}]
$httpBackend.expectGET('data.json').respond(response);
var controller = createController();
$scope.getData();
$httpBackend.flush();
expect($scope.data[0].name).toEqual('naveen')
});
})
here is my code
http://plnkr.co/edit/zdfYdtWbnQz22nEbl6V8?p=preview
http call to get data is effectively getting called twice in the test. One is when the controller is initialized (because you're calling $scope.getData()) and the second is when you manually call $scope.getData() in the spec.
And your expectation is only mocked once (before controller initialisation). To fix the test (to mimic what the controller is actually doing), the expectation has to be set once more before $scope.getData() is called.
See plunker: http://plnkr.co/edit/eLPOZTCgkSfoACLJsVZo?p=preview
OR
You can replace the expectGET with whenGET which doesn't fail the test if the resource is not called. BUT since you're expecting expect($scope.data[0].name).toEqual('naveen') where 'naveen' comes from the http respose, that change should be fine.
I've been facing a trouble while working with Factory/Service. I've created an AjaxRequests factory for all of my AJAX calls. My factory code is
.factory('AjaxRequests', ['$http', function ($http) {
return {
getCampaignsData: function () {
var campaigns
return $http.get(url).then(function (response) {
campaigns = response.data;
return campaigns;
});
}
}
}])
I've created another service in which I am injecting this factory. My service code
.service('CampaignsService', ['$rootScope', 'AjaxRequests', function ($rootScope, AjaxRequests) {
this.init = function () {
this.camps;
AjaxRequests.getCampaignsData().then(function (response) {
this.camps = response.campaigns;
console.log(this.camps); // It is showing data
})
console.log(this.camps); // But it is not working :(
};
this.init();
}])
And in my controller
.controller('AdvanceSettingsController', ['$scope', 'CampaignsService', function ($scope, CampaignsService) {
$scope.CampaignsService = CampaignsService;
}
])
I've read this article to learn promises but it is not working here. I can directly achieve it in controller and it's been working fine. But it consider as a bad coding standard to make controller thick. But when I use service and factory I stuck. My question is why I am not getting ajax data to use in my whole service ? I need to use CampaignsService.camps in my view template as well as in my whole rest script but every time I get undefined. What is happening here? I've asked the same question before but couldn't get any success. Some one please help me to understand about promises and why I am getting this type of error if I'm working same ? This type of question has already been asked before but it was working in controller. May be I am stuck because I'm using it in a service.
A big thanks in advance.
This is not a bug or some tricky functionality. Just like in any other AJAX implementation, you can only access the response data in AngularJS's $http success method. That's because of the asynchronous nature of Asynchronous JavaScript And XML.
And what you have is working.
.controller('AdvanceSettingsController', ['$scope', 'AjaxRequests', function ($scope, AjaxRequests) {
$scope.camps = [];
AjaxRequests.getCampaignsData().then(function(data) {
$scope.camps = data;
});
}
])
And then bind camps:
<div ng-repeat="camp in camps>{{camp.name}}</div>
What's bad in your implementation is that instead of grouping related stuff in services you are writing a big AjaxRequests service for everything. You should have a CampaignsService that has a getData method and inject that in your controller.
Why is this working? Because $http does a $scope.$apply for you, which triggers a digest cycle after the data is loaded (then) and updates the HTML. So before the then callback that ng-repeat is run with [] and after it it's again run but with data from the response because you are setting $scope.camps = data;.
The reason <div ng-repeat="camp in CampaignsService.camps>{{camp.name}}</div> does not work is because of function variable scoping.
The this reference inside of your then callback is not the same as the this reference outside of it.
This will work and uses the common var self = this trick:
var self = this;
this.camps = [];
this.init = function () {
AjaxRequests.getCampaignsData().then(function (response) {
// here "this" is not the one from outside.
// "self" on the other hand is!
self.camps = response.campaigns;
});
};
This question already has answers here:
Angular Best practice: promise in a Factory or in a Controller?
(3 answers)
Closed 7 years ago.
Pretty new to Angular, what I want to ask is which practice is considered better between
Sending promise to the controller
Controller
factory.method()
.success(function (data) {
// do stuff
})
.error(function (data) {
// throw error
});
Service
return {
method: function() {
return $http.get(url);
}
};
and
Sending data to the controller
Controller
myValue = factory.method();
Service
return $http.get(url).then(function(req){
return req.data;
});
Note that I might be completely off-road here and second method might even not work (haven't tested it yet), but just wanted to ask out of curiosity. If there are better or more effectives practices I would be really glad to hear about them, thank you all very much.
I usually use the first solution that I can confirm it works pretty well. Among other things, for example it allows you to :
control asynchronous flow from your controllers
thus chain services, paralellize and join them, show spinners and stuff
reuse the same services in other asynchronous contexts, such as routes resolution
handle promise rejection
Edit:
That said, in addition, you could do both, like Restangular does with "enhanced promises". Returning a thenable thing, with an $object or $return or whatever attached to it would allow you to :
Use the promise
myService.myMethod.then(
function(data) {//Success
//Manipulate data
$scope.whatever = data;
},
function(err) {
//Handle error
}
);
Or just the $return, that will be populated later, when promise resolves
$scope.whatever = myService.myMethod().$return;
//Notice that you just can't handle rejection
An example of service like that, using angular $q service :
var deferred = $q.defer();
//Create $return reference
deferred.promise.$return = [];
deferred.promise.then(function(data) {
//replace $return elements with data elements, keeping reference
angular.copy(data, deferred.promise.$return);
});
setTimeout(function() {
deferred.resolve([
'White',
'Pinkman'
]);
}, 1000);
return deferred.promise;
Haven't tested this code, but you get the idea
This question already has answers here:
Call AngularJS from legacy code
(7 answers)
Closed 9 years ago.
I have an angular service
app.factory('MyService', function($http,$q)){
return{
super : function(){
return "Angular is awesome";
}
};
});
and a complex javascript object defined outside Angular's scope (controller or service):
var MyObject = {
anyFunction : function(){
alert(MyService.super());
}
};
Now, doing
MyObject.anyFunction();
of course fails. Any idea how I can get MyService injected into my external javascript object?
This is bad way, byt you may save your angular's var to the localStorage and then acces it from legacy code, and as a second option, you may access global variable from factory, using $window service.
In common js:
var myVar;
In factory:
app.factory('MyService', ['$window', '$http', '$q',function($window, $http, $q)){
return{
super : function(){
$window.myVar = 'that is it';
//or
//localStorage.addItem('myVar', 'varValue');
}
};
}]);
after MyService.super is done, you may access var in common js as usualy before