Basically i have a angular resource API service as follow. I have use the nested chaining method as below which i think is not so good in coding perspective (especially when there are multiple chaining needed)
angular.module('user')
.factory('UserAPI', ['$resource'],
function ($resource) {
return $resource('User', {},
{
GetUserDetail1: {
method: 'GET',
url: url1
},
GetUserDetail2: {
method: 'GET',
url: url2
}
}
}
)
UserAPI.GetUserDetail1({ ID: id }).$promise.then(function (res) {
UserAPI.GetUserDetail2({ ID: res.userID }).$promise.then(function (res1) {
}, function (errRes1) {
});
}, function (errRes) {
});
So, I am now thinking of refactoring the code as follow but I am not sure whether this could be done.
function getUserDetail2 (res) {
};
UserAPI.GetUserDetails1({ ID: id})
.then(getUserDetail2(res))
.catch(function (errRes) {
// catch error if any error occur
});
You just need to pass reference of function instead of calling it there.
UserAPI.GetUserDetails1({ ID: id})
.then(getUserDetail2) //passed getUserDetail2 method here
.catch(function (errRes) {
// catch error if any error occur
});
Related
I have the following code, but I'm not sure how to add a success/error handler to the request.
$resource('/example.json', {}, {
get_something:
method: 'POST'
url: '/example/get_something.json'
})
I thought I would be able to add success: or something similar here, but apparently that's not the case. How can I do something after this request is completed?
You can handle the response (success/error/exception) as follows:
var example = $resource('/example.json', {}, {
get_something: {
method: 'GET'
}
});
var postParams = {}; // Define post params if any. If you have any post params just use example.get_something()
example.get_something(postParams)
.$promise.then(function(response) {
console.log(response);
}, function(error) {
console.log(error);
})
.catch(function(exception) {
console.log(exception);
});
My service code:
application.factory('Http', function($http) {
var base_url = "Angular_Database/server.php";
return {
post: function(form_data) {
var request = $http({
method: 'POST',
url: base_url,
data: form_data
});
return request;
},
send: function(request, callback) {
request.then(function(response) {
callback(response);
}).error(function(Object) {
alert(Object.data);
});
}
}
})
here, The problem is in the .then().
My console says:
Type:Error request.then(...) error is not a function
There is no error() function in the HttpPromise object starting from Angular 1.5.X (Based on comment). You need to use catch() function instead of it.
request.then(function(response) {
callback(response);
}).catch(function(Object) {
alert(Object.data);
});
Also could be:
request.then(function(response) {
callback(response);
}, function(error){
alert(error.data);
})
I have a service in separate JS file, this service is like OOP class that holds 'methods' to load necessary data from the web.
I want call those 'methods' and get the data in my main JS file, actually I want to load data of three types and force JS flow to wait untill that data is retrieved, here's my code:
services.js
// My 'Class' to load data from the web server
myApp.factory("LoadData", ["_gl", function (_gl) {
return {
GetUsers: function ($http) {
$http({
method: 'POST',
url: 'http://localhost/dgis/ps/select.php',
data: { "action": "GetUsers" }
}).then(function successCallback(response) {
// Save the response JSON object to my global objects
_gl.myUsers = response.data;
}, function errorCallback(response) {
console.log("GetUsersError:" + response);
});
},
GetObGroups: function ($http) {
$http({
method: 'POST',
url: 'http://localhost/dgis/ps/select.php',
data: { "action": "GetObGroups" }
}).then(function successCallback(response) {
// Save the response JSON object to my global objects
// This code fills array because it iterates through it
angular.forEach(response.data, function (value, key) {
_gl.myObGroups.push(value)
});
}, function errorCallback(response) {
console.log("GetObGroups:" + response);
});
},
GetObjects: function ($http) {
$http({
method: 'POST',
url: 'http://localhost/dgis/ps/select.php',
data: { "action": "GetObjects" }
}).then(function successCallback(response) {
_gl.myObjects = response.data;
}, function errorCallback(response) {
console.log("GetObjectsError:" + response);
});
}
}
}]);
// My global variables
myApp.factory('_gl', function () {
return {
myUsers: [],
myOrganisations: [],
myObGroups: [],
myObjects: []
}
});
script.js
Q.all([LoadData.GetUsers($http), LoadData.GetObGroups($http), LoadData.GetObjects($http)]).then(function () {
console.log(_gl.myUsers);
console.log(_gl.myObGroups);
console.log(_gl.myObjects);
});
The problem is, the Q.all won't wait till all http request will get the data, it evaluates calls in then before it happens. Sure, I could use some timer and just wait for a second, but I want more proper way to do that, please share with your knowledge.
And one more thing, if I use forEach in then of my get methods then arrays filling all right, but other arrays are empty and I want to know why it happens.
Thank you.
You have to return the promises in GetUsers, GetObGroups and GetObjects, otherwise Q.all can't do its job.
Therefore, e.g.:
GetUsers: function ($http) {
return $http({
....
should do the trick.
I'm attemping to call a RESTful method via $resource as following:
Resource:
angular.module('secure',['ngResource']).factory('Vehicle', function ($resource) {
return $resource('/secure/vehicle/index', { id: '#id' }, {
query: {
method: 'GET',
isArray: true
},
delete: {
method: 'DELETE',
isArray: false,
url: '/secure/vehicle/delete/:id'
}
});
});
Then, from other service I inject the above factory and I call DELETE method in this way:
factory.delete = function (procedureId) {
var vehicle = new Vehicle();
vehicle.$delete({id: procedureId}, function () {
//success
deferred.resolve();
}, function (errResponse) {
// fail
console.log(errResponse);
});
return deferred.promise;
};
(Don't pay attention to deferred things, it doesn't work with or without it)
Unfortunately, I always get the same answer:
Remote Address:127.0.0.1:8080
Request URL:http://localhost:8080/secure/vehicle/delete/21
Request Method:DELETE
Status Code:422 Unprocessable Entity
The call itself is set up properly (secure/vehicle/delete/21). In fact, if I do the same, but instead of using $resource variable, using $http, everything works!
$http({
'method': 'DELETE',
'url': '/secure/vehicle/delete/' + procedureId,
'headers': {
'Content-Type': 'application/json'
},
'data': ""
})
.success(function () {
// success
})
.error(function (data, status) {
console.log(data.errors);
});
So, I guess something is missing in $resource-way, but what? Any help, it will be appreciated!
EDIT:
It seems it's a backend problem when it reads the entire url call. If I call DELETE resource, using $http, adding the data: "" as I show above, the backend initializes itself properly.
But if I try the $resource-way, the required params are pre-configured and that doesn't like to the backend, so I need to find the way to say to $resource how to add something like data: "", any ideas?
Test proof that it works:
angular.module('secure', ['ngResource']).factory('Vehicle', function($resource) {
return $resource('/secure/vehicle/index', {
id: '#id'
}, {
query: {
method: 'GET',
isArray: true
},
delete: {
method: 'DELETE',
isArray: false,
url: '/secure/vehicle/delete/:id'
}
});
});
angular.module('secure').factory('VehicleFactory', function(Vehicle, $q) {
var factory = {}
factory.delete = function(procedureId) {
var deferred = $q.defer();
var vehicle = new Vehicle();
vehicle.$delete({
id: procedureId
}, function(r) {
deferred.resolve(r);
}, function(errResponse) {
console.log(errResponse);
});
return deferred.promise;
};
return factory;
});
describe('VehicleFactory', function() {
var $httpBackend, VehicleFactory
beforeEach(module('secure'));
beforeEach(inject(function(_$httpBackend_, _VehicleFactory_) {
$httpBackend = _$httpBackend_
VehicleFactory = _VehicleFactory_
}))
it('deletes vehicle - vehicle.$delete()', function() {
var r = {
data: 'correct response'
}
$httpBackend.when('DELETE', '/secure/vehicle/delete/123').respond(r)
VehicleFactory.delete(123).then(function(response) {
expect(response.data).toBe(r.data)
})
$httpBackend.flush();
});
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation()
$httpBackend.verifyNoOutstandingRequest()
})
})
<link href="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine.css" rel="stylesheet" />
<script src="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine-2.0.3-concated.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-resource.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-mocks.js"></script>
Some much cleaner way to write delete functionality without $q:
angular.module('secure').factory('VehicleFactory', function(Vehicle) {
var factory = {}
factory.delete = function(procedureId) {
return (new Vehicle()).$delete({
id: procedureId
})
}
return factory;
});
I have an Angular Service that I'd like to use to perform two $http calls, and return the result of the second. Here's the service:
angular.module('myApp', [])
.service('farm', ['$http']);
function farm($http) {
this.saveFruit = function(fruit) {
return $http.get('http://example.com/get-token').success(function(token) {
return $http({
method: 'POST',
url: 'http://example.com/save-fruit',
headers: { 'X-CSRF-Token': token },
data: { fruit: fruit }
});
});
}
}
At this point, the code works fine. I'm able to "save some fruit", which grabs a token for itself via GET, then sends the data via POST, and everything is saved up in the cloud, great.
To call this service, I'm using code like this:
var fruit = { name: 'Apple', color: 'red' };
farm.saveFruit(fruit).success(function(result) {
console.log(result);
});
However, the console.log() always prints out the result of the $http GET, instead of the POST.
How do I get the result of the $http POST call when calling saveFruit?
Using the .success and .error methods of $http breaks the promise chain. This is undocumented and could be considered a bug.
In order to continue the promise chain, use .then (and .catch, as needed).
return $http.get('http://example.com/get-token').then(function(response) {
return $http({
method: 'POST',
url: 'http://example.com/save-fruit',
headers: { 'X-CSRF-Token': response.data },
data: { fruit: fruit }
});
});
success() doesn't allow chaining promises. Use the real thing: then().
return $http.get('http://example.com/get-token').then(function(response) {
return $http({
method: 'POST',
url: 'http://example.com/save-fruit',
headers: { 'X-CSRF-Token': response.data },
data: { fruit: fruit }
});
}).then(function(response) {
return response.data;
});
and
var fruit = { name: 'Apple', color: 'red' };
farm.saveFruit(fruit).then(function(result) {
console.log(result);
});