I am using 2 service in controller
First Service is to get AjaxResponse where logic to fetching the response is mentioned
The second Service calls the first service to make Http request and get result and then, in turn, return it to the controller
Ctrl Dependency injected firstService,secondService
this.getService = secondService.getData(param);
First Service--> firstService
this.httpResponse(param){
var re = $http.get(param);
return re.then(success,fail);
}
function success(data){
return data;
}
function fail(data){
console.log(data);
}
Second Service (Dependency injection of First Service)
function secondService(firstService){
this.getData = function(param){
return firstService.httpResponse(param);
};
}
this.getService is coming as undefined, all the call are going properly.
Even tried the following code:
secondService.getData(param).then(function(data){console.log(data);});
That doesn't help either.
You should chain the promises in these kinds of situations.
First, you define your service. It should contain two distinct functions. As an example, I did a GET and a POST.
angular.module("myApp",[]).factory("SharedServices", function($http) {
return {
getItem: function() {
return $http.get('path/to/api');
},
postItem: function(payload) {
return $http.post('path/to/api', payload);
}
};
});
Then, reference the service in your controller. getItem() will return a promise, where you can use it using .then to call your second service in the success callback.
angular.module("myApp",[]).controller("MainCtrl", function($scope, SharedServices) {
SharedServices.getItem().then(function(response) {
//success, got something
//call the second part
var payload = { myPayload: response.data.someItem };
SharedServices.postItem(payload).then(function(response) {
//success
}, function(response) {
//an error has occurred to the second call--POST
});
}, function(response) {
//an error occurred to the first call--GET
});
});
Used Callback to get the result.It is similar to deferred(promise)
Related
In angularJS, I have written a directive to display data. This data is fetched by a http service from remote database.
If I apply below timeout service in code, then result is displayed on the html page as http service returns in one second.
$timeout(function () {
$scope.treeRoot = $scope.$eval('serviceResult') || {};
}, 1000);
If i do not use timeout service, then page does not show any data because $scope.treeRoot is empty e.g.
$scope.treeRoot = $scope.$eval('serviceResult') || {};
In production, the http service can take time more than one second to return, is there any generic solution.
You should use Angular's promises or $http service which allows to return a promise.
After the promise, e.g. $http request, is resolved, you can populate $scope.treeRoot with the results.
Let me know if that helps.
AS suggested in one answer you have to use the $http promises and capture the result in response.
Here is an example with some code.
Service:
app.factory('myService', ['$http',
function($http){
var obj = {};
obj.get = function (q) {
return $http.get('/your_get_url')
};
obj.post = function (q, object) {
return $http.post('/your_post_url', object)
};
return obj;
}
]);
In your controller,
allControllers.controller('changePasswordController', ['$scope','myService',
function($scope,myService) {
myService.get().then(function (result) {
$scope.treeRoot = 'use your result here'
},function error(result)
{
console.log(result)
})
}
])
This replaces your timeout issue.
Hi I have small factory (myFactory) in my application:
.factory('myFactory', ['$q', function ($q) {
function myMethod() {
.....
}
return {
myMethod: myMethod
};
}]);
I want to get access to myFactory.myMethod() in protractor test so in onPrepare() I'm using
browser.executeScript(function() {
return angular.element(document).injector().get('myFactory');
}).then(function (myFactory) {
console.log('myFactory: ', myFactory);
myFactory.myMethod();
});
for console.log('myFactory: ', myFactory) I see I get object:
myFactory: {
myMethod: {}
}
Then for myFactory.myMethod(); I see error:
TypeError: object is not a function
Anyone know how I can get access to factory from protractor to be able to execute method?
I use services to access user information in my app via Protractor, I went ahead and played around with this as close to your code as I could, my comment above should be your solution. Here's the longer explanation:
So we have a service Users, with a function called getCurrent() that will retrieve the information of the current user. So first time I tried code similar to yours:
browser.executeScript(function () {
return angular.element(document.body).injector().get('Users');
}).then(function (service) {
console.log(service); // logs object which has getCurrent() inside
service.getCurrent(); // error, getCurrent() is not a function
});
This logged the Users object, and included the function getCurrent(), but I encountered the same error as you when I tried to chain the call service.getCurrent().
What DID work for me, was simply moving the .getCurrent() into the execute script. i.e.
browser.executeScript(function () {
return angular.element(document.body).injector().get('Users').getCurrent();
}).then(function (service) {
console.log(service); // logs John Doe, john.doe#email.com etc.
});
So applying that to your case, the below code should work:
browser.executeScript(function() {
return angular.element(document).injector().get('myFactory').myMethod();
}).then(function (myFactory) {
console.log(myFactory); // this should be your token
});
And just a minor FYI, for what it's worth you also could have written this code by passing in a string to executeScript:
browser.executeScript('return angular.element(document).injector().get("myFactory").myMethod()').then(function (val) {
console.log(val);
});
Am getting an error Error: [$injector:undef] when am using service and http. I couldn't find why is it coming after changing all the changes that has been suggested for this particular error. Kindly check the below code
mainApp.controller('deviceDataController',["$scope","mainService", function ($scope,mainService) {
console.log(mainService);
mainService.deviceDataVar().success(function (data) {
// $scope.deviceDetails = mainService.devices;
console.log(data);
});
}]);
mainApp.factory("mainService",["$http", function ($http) {
angular.forEach(deviceIds, function(value, key) {
var timezone = user_response.timezone;
var DataUrl = LAX_API + "device_info.php?deviceid=" + value + "&limit=288&timezone=" + timezone;
return {
deviceDataVar: function () {
return $http.get(DataUrl).success(function (response) {
devices = response.data;
return devices;
}).error(function (data, status, headers, config) {
// log error
console.log(data)
});;
}
}
});
}]);
kindly help me out with my issue
Thanks!!
Your factory declaration is not valid.
Your factory should return only single method
Create a method that returns $http promises
Agregate all promises inside $q, that will wait for all of them to return a response
Agregate all responses
Return them inside a promise- you cannot return a value, because AJAX calls are async.
Your factory should look like this:
mainApp.factory("mainService", function ($http, $q) {
/* generate single link for deviceID */
function getDevice(value){
var timezone = user_response.timezone;
var dataUrl= LAX_API + "device_info.php?deviceid=" + value + "&limit=288&timezone=" + timezone;
return $http.get(dataUrl);
}
function deviceDataVar(){
// map method will transform list of deviceIds into a list of $http promises
var allRequests = deviceIds.map(getDevice);
// this promise will wait for all calls to end, then return a list of their results
$q.all(allRequests).then(function(arrayOfResults) {
// here you will have all responses, you just need to agregate them into single collection.
// secondly you will need to wrap them into a promise and return
return ...
});
}
/* Return only public methods, at the end */
return {
deviceDataVar: deviceDataVar
}
});
(I was writing this on fly, so there could be few mistakes :), but the conception is right though )
Useful links:
Aggregating promises: angular -- accessing data of multiple http calls - how to resolve the promises
Array.prototype.map: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
How to apss a promise to a factory: How can I pass back a promise from a service in AngularJS?
UPDATE:
To make it work by invokiing small steps you should :
Mock the factory method, let it return a hardcoded value. Return it through a promise.
replace hardcoded value with single (hardcoded) URL to a selected device.
use aggregation ($q.all) for this single $http call.
replace single $http with array made from deviceIds list.
I have a problem with outputting the values of a promise function.
$scope.getTeacher = function(teacherAbr) {
var promise = dataService.getTeacher(teacherAbr);
var testje = promise.then(function(payload) {
return payload;
});
return testje; // outputs an d object, not the direct payload values
};
The output of this controller function is this:
However, when I'm doing testje.$$state it returns undefined. How can I output the value object? I can't output the payload variable in a new $scope, because this data is dynamic.
Here is a simplified version of this on Plunker.
You should change the way you think about things when you work with asynchronous code. You no longer return values, instead you use Promise or callback patterns to invoke code when data becomes available.
In your case your factory can be:
.factory('dataService', function($http, $log, $q) {
return {
getTeacher: function(teacher) {
// Originally this was a jsonp request ('/teacher/' + teacher)
return $http.get('http://echo.jsontest.com/key/value/one/two').then(function(response) {
return response.data;
}, function() {
$log.error(msg, code);
})
}
};
});
And usage in controller:
dataService.getTeacher('Lanc').then(function(data) {
$scope.teacher = data;
});
Also $http.get already returns promise, so you don't have to create one more with $q.defer().
Demo: http://plnkr.co/edit/FNYmZg9NJR7GpjgKkWd6?p=preview
UPD
Here is another effort for combining lessons with teachers.
Demo: http://plnkr.co/edit/SXT5QaiZuiQGZe2Z6pb4?p=preview
//in your services file
return {
getTeacher: function (teacher) {
// Originally this was a jsonp request ('/teacher/' + teacher)
return $http.get('http://echo.jsontest.com/key/value/one/two')
})
//change the controller to this
dataService.getTeacher(teacherAbr).then(function(msg){
$scope.getdata=msg.data;
console.log("From server"+msg.data);
});
I have a factory that returns an object from $http.get
app.factory( 'myFactory', function($http) {
return {
get: function() {
return $http.get('/data').success(function(data) {
return data
})
}
}
})
then
$scope.listings = myFactory.get()
In index.html, I use ng-repeat on listings.data and there is no problem finding each object.
Then from a directive I call .getListings() that's in my controller and in the Chrome Javascript console $scope.listings =
Object {then: function, success: function, error: function, $$v: Object}
Why can't I just use this?
$scope.listings.data
And is it ok to use this?
$scope.listings.$$v.data
What is $$v?
You are making little mistake in your code with get in service you return a promise object which will be filled when you sucessfully complete response from the server so kindly modify your code below to make it working.
app.factory( 'myFactory', function($http) {
return {
get: function() {
return $http.get('/data')
}
}
})
myFactory.get().then(function(data){
$scope.listings=data;
});