AngularJS Http get empty first time - angularjs

I have this code
PedidosService.getProductbyID($scope.listProductos.ProductID).then(function (d) {
$scope.oneProduct = d.data.producto;
});
PedidosService is the name of my factory, getProductbyId is my http get request and $scope.oneProduct is the variable where i want store the result of this request.
factory.getProductbyID = function (id) {
return $http.get('/Pedidos/GetProduct/' + id);
}
factory is my Factory and getProductbyID is my function to call http request
I call this code in a button. The first time that I click in the button, it returns a empty response '[]' but the next times that I click the button, it works fine!!!.
Thanks for you help

As far as I know the $http.get returns a promise because that call is asynchronous. With that in mind a typical call to $http.get should be something like this:
$http.get('/someUrl', config).then(successCallback, errorCallback);
In your context I would have done it this way, so the factory returns a promise and in your controllers you will handle the success and error callback appropriately:
factory.getProductbyID = function (id) {
var deffered = $q.defer();
$http.get('/Pedidos/GetProduct/'+ id)
.then(function (result) {
deffered.resolve(result);
}, function (data) {
deffered.reject(data);
});
return deffered.promise;
}

Related

Web api get call but in reponse it says undefined

I'm trying to call a web api POST method using angular js it get call.
I try from postman utility it also get call and in respose give a json data.But in angular side i am not getting data in response.
my services in angular js
var _getProjects = function (searchText) {
debugger;
return $http.post(URL + 'api/project/GetProjectDetails?searchText='+ searchText).then(function (response) {
return response;
});
};
and below is my web api
[HttpPost]
[Route("api/project/GetProjectDetails")]
public List<GetKeywordsBasisData_Result> GetProjectDetails(string searchText)
{
if (!String.IsNullOrEmpty(searchText))
{
return projectProvider.GetProjectDetails(searchText).ToList();
}
return new List<GetKeywordsBasisData_Result>();
}
You are missing a callback. Http Calls on $http happen asynchronously, you need to pass in a method to call once the call completes. Something like this. The parameter myCallback is a function that takes in the expected response, you can then process it (or whatever) inside that function.
function (searchText, myCallback) {
$http.post(URL + 'api/project/GetProjectDetails?searchText='+ searchText).then(function (response) {
myCallback(response);
});
};
You can then call it from your controller like this assuming getProjects is your factory method. Also assuming that $scope is a field on your controller.
var me = this;
getProjects('somethingToSearchFor', function(results){
me.$scope.results = results;
});

Angular promise callback not firing

I have this app that uploads a file to a server using $cordovaFileTransfer and then sends data about the file to the same server. The file is transferred fine. The data is then sent to the server, and the server responds. But the response does not make it back to the promise callback. Why?
$scope.sendPost = function(data) {
//first upload a file then send more data about the file
$cordovaFileTransfer.upload('http://example.com', 'myfile.txt', options)
.then(function(result) {
var promise = MyFactory.sendFileData(data);
});
promise.then(function(response) {
//we never make it to here
});
}
and in MyFactory:
service.sendFileData = function(data) {
return $http({
//bunch of parameters. This function works, data is sent to the server and a response received
}).then(function(response) {
//this is fired when the response is received from the server. All is good so far.
return.response.data
});
}
return service;
$cordovaFileTransfer.upload returns a promise object, which you could use to build up promise chaining mechanism.
Code
$scope.sendPost = function(data) {
//get hold on `upload` function promise
var promise = $cordovaFileTransfer.upload('http://example.com', 'myfile.txt', options)
.then(function(result)) {
//return MyFactory.sendFileData promise here which will follow promise chaining
return MyFactory.sendFileData(data);
});
//promise.then will get call once `MyFactory.sendFileData` complete it
promise.then(function(response) {
//will get called once `sendFileData` complete its promise
});
}
its because you're relaying on another promise's callback to initiate a the promise and.. most probably before the promise gets initialized you are attaching a callback tot it.. so at the time of you attaching the callback, the promise is not yet initialized i.e. promise is null.. so in your console you'll see an error..
try doing some thing like
var x = function(response) {
//we'll make it to here now...
}
$cordovaFileTransfer.upload('http://example.com', 'myfile.txt', options)
.then(function(result)) {
var promise = MyFactory.sendFileData(data);
promise.then(x);
});
You should follow #PankajParkar solution though it's a better approach...
$scope.sendPost = function(data) {
//first upload a file then send more data about the file
$cordovaFileTransfer.upload('http://example.com', 'myfile.txt', options)
.then(function(result)) {
return MyFactory.sendFileData(result.data);
})
.then(function(response) {
});

$http.get().error() does not call .then() callback

I am still trying to learn Jasmine and test an Angular service. Currently I am trying to test the .success and error calls off http.get.
Service Call
this.get = function (param1, param2) {
return $http.get('api/something/get/param1/param2')
.success(function (data) {
return data;
})
.error(function() {
return "Please select param1 AND param2";
});
};
Jasmine Tests
it('service makes unsuccessful API call', function() {
var response = "This is the response";
httpBackend.when('GET', "api/something/Get/0/0").respond(404);
var data;
service.get(0, 0).then(function(result) {
data = result;
});
httpBackend.flush();
expect(data).toEqual("Please select param1 AND param2");
});
it('service makes successful API call', function () {
var response = "This is the response";
httpBackend.when('GET', "api/something/Get/0/0").respond(response);
var data;
service.get(0, 0).then(function(result) {
data = result.data;
});
httpBackend.flush();
expect(data).toEqual(response);
});
In the first test (Error) the data = result.data line in then() is never called. On the expect(data).toEqual(), data is undefined. When I step through everything I see where the service is called and the error message is populated in result.data.
In the second test (Success), I see the same thing but the data is set when the then function is called.
Why is my then function not called on .error()?
success() and error() don't work the same way as then(). The value returned by the callback is ignored. success() and error() return the promise on which they're called, and not a new promise like then().
So, their usage should be limited to callbacks having side-effects only (like initializing a scope variable).

How to use restangular with promise pattern in angular service

I have a service with rest angular with following structure
function countrySvc(restangular) {
restangular.addResponseInterceptor(function (data, operation, what, url, response, deferred) {
if (operation === 'getList') {
var newResponse = response.data;
return newResponse;
}
return response;
});
var baseCountry = restangular.all('country');
this.countries = function() {
baseCountry.getList();
};
}
also a controller
function countryCtrl(scope, countrySvc) {
scope.countries = countrySvc.countries();
}
but when i access the countries from controller, the result is empty with a successful request with data, my question is how a can extract the data from response with proper promise pattern, ie( i need array of countries when i access scope.countries)
You need to resolve promise...
There are two ways to do it...
1) Using $object
just add .$object to end of promise so once request is done it resolves promise...
scope.countries = countrySvc.countries().$object;
2) Using then
if you need to do some stuff after promise is resolved pick this option, once request is done callback function in then will be fired
scope.countries = countrySvc.countries().then(function (response){
// DO SOMETHING IF YOU NEED BEFORE SET OBJECT
scope.countries = response;
// DO SOMETHING IF YOU NEED AFTER SET OBJECT
});

Subsequent ajax calls in angularJs

I'd like to make subsequent ajax calls in angularJs inside a service.
I've tried with something like this:
var requests = [
{'url': 'call1'},
{'url': 'call2'},
{'url': 'call3'}
];
return $q.all([
$http({
url: requests[0],
method: "POST"
}).then( /*callback*/ ),
$http({
url: requests[1],
method: "POST"
}).then( /*callback*/ )
]);
But this make alla ajax in parallel. I need a way to make this calls subsequent, so after first end, it calls second....
You can chain promises:
var requests =[{'url':'index.html'},
{'url':'index.html'},
{'url':'index.html'}];
function makeCall(n) {
return $http({url:requests[n].url+"?n="+n,method:"GET"}).then(function(r) {
if (n+1<requests.length) return makeCall(n+1);
});
}
makeCall(0);
http://plnkr.co/edit/1HdYUtHKe8WXAFBBq8HE?p=preview
You could use async.eachSeries:
var requests = ['call1', 'call2', 'call3'];
function iterator(request, done) {
$http({
url: request,
method: "POST"
}).then(done);
};
async.eachSeries(
requests,
iterator,
function (err) {
// Done
}
);
From the readme:
eachSeries(arr, iterator, callback)
The same as each only the iterator is applied to each item in the array in series. The next iterator is only called once the current one has completed processing. This means the iterator functions will complete in order.
arr - An array to iterate over.
iterator(item, callback) - A function to apply to each item in the array. The iterator is passed a callback(err) which must be called once it has completed. If no error has occured, the callback should be run without arguments or with an explicit null argument.
callback(err) - A callback which is called after all the iterator functions have finished, or an error has occurred.
You should be able to call another $http call in the "then" callback, returning the return value of $http
$http({...})
.then(function() {
return $http({...});
})
.then(function() {
return $http({...});
});
This works because each call to $http returns a promise. If you return a promise in the "then" success callback, then the next "then" callback in the chain will be deferred until that promise is resolved, which will be when the ajax call completes.
Edit: In response to the comment, you can loop over an array of requests:
var requests = [
{'url':'call1','method':'get'},
{'url':'call2','method':'get'},
{'url':'call3','method':'get'}
];
var promise = null;
angular.forEach(requests, function(details) {
promise = $q.when(promise).then(function() {
return $http(details);
});
});
As in the Plunker at http://plnkr.co/edit/RSMN8WuPOpvdCujtrrZZ?p=preview . The $q.when is just for the first value of the loop, when promise is set to null, so it has a then callback that is called immediately.

Resources