Recall $resource factory within interception - javascript

I have the following factory:
.factory('Request', ['$resource', 'general',
function ($resource) {
return $resource(baseURL + ':resourceName/', {}, {
get : {
method : 'GET',
isArray : true,
transformResponse : function (data, headers) {
return JSON.parse(data).data;
},
interceptor: {
responseError : function (data) {
gnrl.logIn({},false,function(){console.log("test");});
// ???? How to recall this request?
}
}
}
});
}
]);
What I'm trying to do is, if the user has some trouble in this request, the user should login again and the request should be executed again.
The request factory is called as follows:
Request.get(params, headers, function (res) {
//does some operation with results
});
I have seen some related questions but none of them could fit my situation completely.

It is solved using the answers referred in the question. As said, the main idea was using $promise instead of interceptor.
I have solved the problem as follows:
The following is a function in my service
self.doRequest = function(nOfRetries, params, successFunction) {
function fai(a) {
nOfRetries--;
self.logIn(function(){self.doRequest(nOfRetries);});
}
if (nOfRetries >= 0) {
Request.get(params).then(successFunction).catch(fai);
}
}
Login is just another function in the same service and as a callback function i send a request to this function.
doRequest is called as follows:
general.doRequest(3, params/*parameters used in request*/, function (res) {
/***cb function for your initially request*/
});
As last, you see the Request factory:
.factory('Request', ['$resource',
function ($resource) {
var res = $resource(baseURL + ':resourceName/', {}, {
get : {
method : 'GET'
}
});
return {
get : function (arguments) {
return res.get(arguments).$promise;
}
};
}
])
Note that any error (server-side or not) occurred in doRequest's success callback function will also lead to executing failure callback function.

Related

get Alfresco.util.Ajax.request response.json data from external function

I have an alfresco webscript who return a json response.
I have a js function getWorkflowRepositoryContent() who call this webscript and get the data retuned in the response.
I store the response.json in an array list.
All works fine for me, but when i call getWorkflowRepositoryContent() from another js function, it returned an empty array when it must return an array containing the data received from webscript response.
There is the function where i return the data received from the webscript.
Can you tell me what i made a mistake, or tell me how to properly return the data from that function.
function getWorkflowRepositoryContent(){
var list=[];
var workflowFilesNameAndNodeRef;
var test=function getWorkflowFilesList(response)
{
workflowFilesNameAndNodeRef=response.json.nodes;
$.each(response.json.nodes,function(index,value){
list.push(value.name);
});
}
Alfresco.util.Ajax.request(
{
method:Alfresco.util.Ajax.GET,
url: Alfresco.constants.PROXY_URI + "/ALFRESCO-DIRECTORY",
successCallback:
{
fn:test,
scope:this
},
failureCallback:
{
fn: function(response)
{
Alfresco.util.PopupManager.displayMessage({text:"Failure"});
},
scope: this
}
});
console.log(list.length);
return list;
}
Your getWorkflowRepositoryContent is getting asynchronous data but returning synchronously so your example won't work.
An easy way would be to simple call your function with a callback argument.
function getWorkflowRepositoryContent(cb){ // pass a callback as an argument
var list=[];
var workflowFilesNameAndNodeRef;
var test=function getWorkflowFilesList(response)
{
workflowFilesNameAndNodeRef=response.json.nodes;
console.log(response.json.nodes);
$.each(response.json.nodes,function(index,value){
list.push(value.name);
});
$.each(list,function(index, fileName){
$('<option/>').val(fileName).html(fileName).appendTo('#saveButton');
$('<option/>').val(fileName).html(fileName).appendTo('#loadButton');
});
cb(list); // call the callback once the work is done
}
Alfresco.util.Ajax.request(
{
method:Alfresco.util.Ajax.GET,
url: Alfresco.constants.PROXY_URI + "/ALFRESCO-DIRECTORY",
successCallback:
{
fn:test,
scope:this
},
failureCallback:
{
fn: function(response)
{
Alfresco.util.PopupManager.displayMessage({text:"Failure To get StarXpert Workflow content"});
},
scope: this
}
});
}
getWorkflowRepositoryContent( function(list) {
console.log(list);
});
You could also use promises but it might be a little harder if you're not familiar with them.

AngularJs calling multiple service function : which is the best way to call multiple REST service on angularjs during the init step?

I have this infrastructure
[play] <-REST-> [karaf]
and this controller
$scope.getPrototypes = function (node) {
connectHttpService.getPrototypes(function (response) {
$scope.prototypes = response;
}, node);
}
$scope.getCommandsWithAck = function (node) {
connectHttpService.getCommands(function (response) {
$scope.commandsWithAck = response;
}, node, true);
}
$scope.getCommandsWithoutAck = function (node) {
connectHttpService.getCommands(function (response) {
$scope.commandsWithoutAck = response;
}, node, false);
}
where connectHttpService is the service
function getCommands(successHandler, failHandler, nodeId, ack) {
$http({
method: 'GET',
........MY ENDPOINT.........
}
}).success(function(response) {
successHandler(response);
}).error(function(response) {
console.log("connectHttpService got an error response: " + JSON.stringify(response));
})
}
the problem is my init method (called thorugh ng-init) is
$scope.initCommands = function () {
$scope.currentNode = $stateParams.node;
$scope.getPrototypes($scope.currentNode); //(1)
$scope.getCommandsWithAck($scope.currentNode); //(2)
$scope.getCommandsWithoutAck($scope.currentNode); //(3)
}
}
the $scope.getCommandsWithoutAck is called but doesn't return. On the server side (karaf) I see the call and the response. No error on the browser.
if I remove (1) or (2) it works
if I change the position of (3) and (2) it works, but only since (2) doesn't return nothing.
In other words: which is the best way to call multiple REST service on angularjs during the init step?
Try to use $q
Like this
$scope.currentNode = $stateParams.node;
$q.all([
$scope.getPrototypes($scope.currentNode), //(1)
$scope.getCommandsWithAck($scope.currentNode), //(2)
$scope.getCommandsWithoutAck($scope.currentNode) //(3)
]).then(function(result){
console.log(result[0]);//(1)
console.log(result[1]);//(2)
console.log(result[2]);//(3)
});
And you have to return promise from service
Like this
$scope.getCommandsWithAck = function (node) {
return connectHttpService.getCommands(function (response) {
$scope.commandsWithAck = response.data;
return $scope.commandsWithAck; //to complete promise
}, node, true);
}
N:B: you have to inject $q in your controller

How to make multiple http requests in my case

I'm trying to chain a promise with Angular $resource.
I have the following factory:
angular.module('myApp').factory('Product', ['$resource', function ($resource) {
return $resource(
'/api/product/:name',
{ name: '#name' },
{ 'getSub': {
url: '/api/product/getSub/:name',
method: 'GET'}
}
);
}]);
I make multiple queries using my Product factory as such:
Product.query({'name': name}, function(product) {
Product.getSub({'name': product.name}, function(subItem) {
Product.getSub({'name':subItem.name}, function(childItem) {
//do stuff with child item
})
})
})
Is there a better way to do this? I feel like nesting all these calls is not a best practice.
You can chain the promises together!
Product.query({'name': name}).$promise
.then(function(product){
return Product.getSub({'name': product.name}).$promise;
})
.then(function(subItem){
return Product.getSub({'name': subItem.name}).$promise;
})
.then(function(item){
// etc
})
you can use waterfall of async library or implement it yourself.
here's sample code for your case.
async.waterfall([
function(callback) {
Product.query({'name': name}, function(product) {
callback(null, product);
})
},
function(product, callback) {
Product.getSub({'name': product.name}, function(subItem) {
callback(null, product, subItem);
})
},
function(product, subItem, callback) {
Product.getSub({'name':subItem.name}, function(childItem) {
var result = {};
result.childItem = childItem;
result.subItem = subItem;
result.product = product;
callback(null, result);
})
}
], function (err, result) {
//do stuff with result
});
If you want the requests to be done one after another (like you have in your example) you could do a recursive function like this:
in this example i want to upload a couple of images (calling a http route):
$scope.uploadImageLayout = function (currentIndex, numberOfItems) {
if (currentIndex === numberOfItems) {
// in here you could do some last code after everything is done
} else {
Upload.upload({
url: 'localhost:3000/ficheiros',
file: $scope.imagesToUpload[$scope.auxIndex].file
}).success(function (data, status, headers, config) {
if ($scope.auxIndex < numberOfItems) {
$scope.uploadImageLayout(currentIndex + 1, numberOfItems);
}
});
}
};
and the first time you call just do this:
$scope.uploadImageLayout(0, $scope.imagesToUpload.length);
in you case its the same but instead of the Upload.upload request you should have your request and catch the callback function(s).
A useful solution maybe use $q library
https://docs.angularjs.org/api/ng/service/$q
You can use the method $q.all() to send a lot of request and manage only one callback then() or make $q.defer() and resolve por reject your oun promises.
I currently answer this question from a mobile device and i can't make an example. Sorry about that.
If when I get home that mistake trains still try to help

displaying Data from multiple tables with AngularJs

I have been reading different posts with similar questions but I cannot get this figured out. I have a Job class that is linked to different tables such as Customer and Employee. The Data is coming back from the Database but I cannot get the Angular Table to display the linked classes. The suggestions have been to use different mods, restangular, angular-activerecord, ModelCore and this method
angular js model relationships
I am not sure the best route to take and what would be the simplest way of doing it.
app.factory('Job', function ($resource) {
return $resource('/api/apiJob/:id',
{ id: '#id' },
{ 'save': { method: 'POST' } },
{ 'update': { method: 'PUT' } },
{ 'query': { method: 'GET', isArray: false } });
});
app.factory('jobFactory', function ($http) {
return {
updateJob: function (job) {
return $http.put('/api/apiJob/' + job.JobId, job);
}
};
});
app.factory('Customer', function ($resource) {
return $resource('/api/apiCustomer/:id',
{ id: '#id' },
{ 'save': { method: 'POST' } },
{ 'update': { method: 'PUT' } },
{ 'query': { method: 'GET', isArray: false } });
});
app.factory('customerFactory', function ($http) {
return {
updateCustomer: function (customer) {
return $http.put('/api/apiCustomer/' + customer.CustomerId, customer);
}
};
});
'use strict';
app.controller('JobCtrl', function ($scope, Job, $resource, $route, jobFactory, notificationFactory, $http) {
////GET Jobs
$scope.jobArray = Job.query()
//New Job Modal
$scope.NewJobModal = function () {
$('#NewJobModal').modal();
}
$scope.submitJob = function () {
var data = {
JobId: $scope.JobId,
JobNumber: $scope.JobNumber,
JobName: $scope.JobName,
CustomerName: $scope.CustomerName,
JobDescription: $scope.JobDescription,
OriginalContract: $scope.OriginalContract,
BillingDate: $scope.BillingDate,
}
$http.post('/api/apiJob/PostNewJob', data).success(function (data, status, headers) {
console.log(data);
});
window.top.location.reload();
};
//End New Job Post
//Delete Job
$scope.deleteJob = function (job) {
Job.delete({ id: job.JobId }, function () {
if ($scope.jobArray.length === 1) {
$scope.jobArray.splice(-1, 2);
} else {
$scope.jobArray.splice(job.JobId - 1, 2);
}
window.top.location.reload();
});
};
//End Delete Job
$scope.updateJob = function (job) {
jobFactory.updateJob(job).success(successCallback).error(errorCallback);
};
$scope.job = [];
var successCallback = function (data, status, headers, config) {
notificationFactory.success();
return $('#editJobModal').modal('hide');
};
var errorCallback = function (data, status, headers, config) {
notificationFactory.error(data.ExceptionMessage);
};
//End Edit Job
}); //End Job Controller
What It looks like in the Browser Console
0: {$id:1, JobId:1, JobNumber:2534, JobName:St.Lukes, JobDescription:Rebuilding Cafeteria,…}
$id: "1"
BalanceDue: 89654123
BalanceToBill: 541256
BillingDate: "2014-08-12T14:43:22.507"
BillingForm: "Invoice"
Budget: 854523658
CertPayroll: true
ChangeOrders: [{$id:4, ChangeOrderId:1, ChangeOrderNumber:7854, ChangeOrderDate:2014-08-12T14:43:22.673,…}]
ContractDate: "2014-08-12T14:43:22.507"
Customers: [{$id:2, CustomerId:2, CustomerName:Grove at Wilcrest, CustomerPhoneNumber:8327899667,…}]
0: {$id:2, CustomerId:2, CustomerName:Grove at Wilcrest, CustomerPhoneNumber:8327899667,…}
Employees: [{$id:3, EmployeeId:2, AccountName:Ham Sandwich, EmployeeFirstName:Scott, EmployeeLastName:Willis,…}]
JobAddress: "1234 Mason Rd"
JobCity: "Katy"
JobCost: 784556124
Updated Factory
app.factory('JobGet', function ($http, $q) {
var data = $http({
method: 'GET',
url: '/api/apiJob'
})
return {
query: function () {
var deferred = $q.defer();
setTimeout(function () {
deferred.resolve(data)
}, 2000);
return deferred.promise;
}
};
});
Network Response Tab
[{"$id":"1","JobId":1,"JobNumber":2534,"JobName":"St.Lukes","JobDescription":"Rebuilding Cafeteria","OriginalContract":1250210,"ContractDate":"2014-08-12T14:43:22.507","BillingDate":"2014-08-12T14:43:22.507","TotalCO":12502105,"RevisedContract":452136852,"Budget":854523658,"BillingForm":"Invoice","TESPM":"Frank Harvel","TESSuperintendent":"Rudy Sanchez","Status":"Active","MoreShit":"More shit goes here","TaxExempt":true,"CertPayroll":true,"JobCost":784556124,"RemainingBudget":96523145,"Profit":854125,"Percentage":45,"TotalBilled":45236554,"BalanceToBill":541256,"PaidToDate":0,"BalanceDue":89654123,"JobAddress":"1234 Mason Rd","JobCity":"Katy","JobState":"TX","JobZipcode":77493,"JobCounty":"Harris","JobPhone":2814569654,"JobFax":2814563251,"JobHidden":false,"Customers":[{"$id":"2","CustomerId":2,"CustomerName":"Grove at Wilcrest","CustomerPhoneNumber":8327899667,"CustomerFaxNumber":7134568547,"CustomerAddress":"56328 Richmond Ave","CustomerCity":"Houston","CustomerState":"TX","CustomerZipcode":77042,"CustomerWebsite":"grovewilcrest.com","CustomerOtherShit":"Other Shit Goes here","CustomerHidden":false,"CustomerPM":null,"CustomerAdmin":"Jane Miller","CustomerAccountant":"Betsy Sue","TESSuperintendent":null,"JobId":1,"Job":{"$ref":"1"}}],"Employees":[{"$id":"3","EmployeeId":2,"AccountName":"Ham Sandwich","EmployeeFirstName":"Scott","EmployeeLastName":"Willis","EmployeeTitle":"Admin","EmployeeCellPhone":2818567854,"EmployeeOfficePhone":7134527854,"EmployeeEmail":"testing#gmail.com","CompanyEmployeeId":12521,"EmployeeHidden":false,"EmployeeIsSuper":true,"EmployeeIsPM":true,"JobId":1,"Job":{"$ref":"1"}}],"ChangeOrders":[{"$id":"4","ChangeOrderId":1,"ChangeOrderNumber":7854,"ChangeOrderDate":"2014-08-12T14:43:22.673","ChangeOrderName":"Insert Name Here","ChangeOrderDescription":"It changed","ChangeOrderAmount":4000,"ChangeOrderApprovedDate":"2014-08-12T14:43:22.673","ChangeOrderApprovedAmount":3000,"ChangeOrderApprovedNumber":1,"ChangeOrderAttn":"Frank Harvel","ChangeOrderHidden":false,"JobId":1,"Job":{"$ref":"1"}}]},{"$id":"5","JobId":2,"JobNumber":12343,"JobName":"Katy Mills","JobDescription":"New Mall Bathrooms","OriginalContract":32623212,"ContractDate":"2014-08-12T14:43:22.507","BillingDate":"2014-08-12T14:43:22.507","TotalCO":12502105,"RevisedContract":452136852,"Budget":854523658,"BillingForm":"Invoice","TESPM":"Frank Harvel","TESSuperintendent":"Mike Hall","Status":"Active","MoreShit":"More shit goes here","TaxExempt":true,"CertPayroll":true,"JobCost":784556124,"RemainingBudget":96523145,"Profit":854125,"Percentage":45,"TotalBilled":45236554,"BalanceToBill":541256,"PaidToDate":0,"BalanceDue":89654123,"JobAddress":"1234 Mason Rd","JobCity":"Katy","JobState":"TX","JobZipcode":77493,"JobCounty":"Harris","JobPhone":2814456965,"JobFax":2814563225,"JobHidden":false,"Customers":[{"$id":"6","CustomerId":1,"CustomerName":"City Center","CustomerPhoneNumber":8327899667,"CustomerFaxNumber":7134568547,"CustomerAddress":"123453 HWY 6","CustomerCity":"Katy","CustomerState":"TX","CustomerZipcode":77493,"CustomerWebsite":"citycenter.com","CustomerOtherShit":"Other Shit Goes here","CustomerHidden":false,"CustomerPM":null,"CustomerAdmin":"Jane Miller","CustomerAccountant":"Betsy Sue","TESSuperintendent":null,"JobId":2,"Job":{"$ref":"5"}}],"Employees":[{"$id":"7","EmployeeId":3,"AccountName":"Ice Cream","EmployeeFirstName":"Aaron","EmployeeLastName":"Horstmann","EmployeeTitle":"Office Bitch","EmployeeCellPhone":2818567854,"EmployeeOfficePhone":7134527854,"EmployeeEmail":"aaron#gmail.com","CompanyEmployeeId":12521,"EmployeeHidden":false,"EmployeeIsSuper":true,"EmployeeIsPM":true,"JobId":2,"Job":{"$ref":"5"}}],"ChangeOrders":[{"$id":"8","ChangeOrderId":2,"ChangeOrderNumber":1823,"ChangeOrderDate":"2014-08-12T14:43:22.673","ChangeOrderName":"Insert Name Here","ChangeOrderDescription":"Work Orders","ChangeOrderAmount":4000,"ChangeOrderApprovedDate":"2014-08-12T14:43:22.673","ChangeOrderApprovedAmount":3000,"ChangeOrderApprovedNumber":2,"ChangeOrderAttn":"Rosie Sanchez","ChangeOrderHidden":false,"JobId":2,"Job":{"$ref":"5"}}]},{"$id":"9","JobId":3,"JobNumber":12398,"JobName":"City Center","JobDescription":"Remodeling Yard House","OriginalContract":56325412,"ContractDate":"2014-08-12T14:43:22.507","BillingDate":"2014-08-12T14:43:22.507","TotalCO":12502105,"RevisedContract":452136852,"Budget":854523658,"BillingForm":"Invoice","TESPM":"Frank Harvel","TESSuperintendent":"Shawn Saulnier","Status":"Active","MoreShit":"More shit goes here","TaxExempt":true,"CertPayroll":true,"JobCost":784556124,"RemainingBudget":96523145,"Profit":854125,"Percentage":45,"TotalBilled":45236554,"BalanceToBill":541256,"PaidToDate":0,"BalanceDue":89654123,"JobAddress":"1234 Mason Rd","JobCity":"Katy","JobState":"TX","JobZipcode":77493,"JobCounty":"Harris","JobPhone":2814256965,"JobFax":2814565325,"JobHidden":false,"Customers":[{"$id":"10","CustomerId":3,"CustomerName":"Twin Peaks","CustomerPhoneNumber":8327899667,"CustomerFaxNumber":7134568547,"CustomerAddress":"8473 Katy Fwy","CustomerCity":"Houston","CustomerState":"TX","CustomerZipcode":77043,"CustomerWebsite":"citycenter.com","CustomerOtherShit":"Other Shit Goes here","CustomerHidden":false,"CustomerPM":null,"CustomerAdmin":"Jane Miller","CustomerAccountant":"Betsy Sue","TESSuperintendent":null,"JobId":3,"Job":{"$ref":"9"}}],"Employees":[{"$id":"11","EmployeeId":1,"AccountName":"Not Sure","EmployeeFirstName":"Frank","EmployeeLastName":"Harvel","EmployeeTitle":"Manager","EmployeeCellPhone":2818567854,"EmployeeOfficePhone":7134527854,"EmployeeEmail":"texas45#gmail.com","CompanyEmployeeId":12521,"EmployeeHidden":false,"EmployeeIsSuper":true,"EmployeeIsPM":false,"JobId":3,"Job":{"$ref":"9"}}],"ChangeOrders":[{"$id":"12","ChangeOrderId":3,"ChangeOrderNumber":45324,"ChangeOrderDate":"2014-08-12T14:43:22.673","ChangeOrderName":"Insert Name Here","ChangeOrderDescription":"It changed again","ChangeOrderAmount":4000,"ChangeOrderApprovedDate":"2014-08-12T14:43:22.673","ChangeOrderApprovedAmount":3000,"ChangeOrderApprovedNumber":3,"ChangeOrderAttn":"Travis Dillard","ChangeOrderHidden":false,"JobId":3,"Job":{"$ref":"9"}}]}]
First of all, this is a work in progress. Your code is very large and to solve this I removed a lot o noise from your plunkr, I left there only what's essential to make it work and only the code involved in it.
Working Demo
First thing to notice, on your JobController you are doing:
////GET Jobs
$scope.jobArray = Job.query();
This worked on previous versions of angular, on the current version there is no automatic promise unwrapping anymore, so you must use the then function:
////GET Jobs
Job.query().then(function(retrievedData){
$scope.jobArray = retrievedData;
});
Notice that on the plunkr I "mocked" the returning of data using $q and a timeout, I actually cleaned the json leaving only the properties that are used on the table, just to make it simpler, you don't need to do that on your code ok? Just keep that part as it is.
Maybe you'll have to modify it just to resolve the promise with the returned data, but this is up to you, the important thing is to return a promise from your query() method and resolve it.
On the HTML I noticed that you are binding the customer name like this:
<td>{{job.Customers.CustomerName}}</td>
But on your Json, the Customers property is an array of customers, so you either return one customer from your api or bind it like this:
<td>{{job.Customers[0].CustomerName}}</td>
I also noticed that there are a lot of jQuery references on your controllers like this:
$('#editJobModal').modal();
This is not recommended and I don't think it will work at all, when dealing with the DOM, always use directives and comunicate with them using bindings, thats the angular way.
Well after all this, my plunkr is showing the table with the 2 fake customers from the Json. Now I suggest you to study that code and apply those principles to your app.
I hope I could help or at least point you at the right direction.

AngularJS $resource parameter is not replaced with its real value?

I have recently decided to use $resource for REST service, but I quickly got in trouble. I have a simple URL:
/r/interface/activate/:active/addr/:address
But calling it in unit test make it fail with:
// expected: POST /r/interface/activate/false/addr/123
// got : POST /r/interface/activate/false/addr/#address
My defined resource is :
module.factory('NetworkInterfaceActivationService', function ($resource) {
return $resource("/r/interface/activate/:active/addr/:address", {}, {
activate:{method:'POST', params:{active:"true", address:'#address'}, isArray:false},
deactivate:{method:'POST', params:{active:"false", address:'#address'}, isArray:false}
});
});
And this is how I call my service !
$scope.deactivateNetworkAddress = function (address) {
NetworkInterfaceActivationService.deactivate({address:address});
};
Am I missing something?
I tried your code with Angular 1.3, but I couldn't reproduce the problem.
jsFiddle
<button ng-click="parentCtrl.doIt('123foobar')">execute</button>
app.controller('ParentCtrl', function (NetworkInterfaceActivationService) {
this.doIt = function (address) {
NetworkInterfaceActivationService.deactivate({address:address});
};
})
app.factory('NetworkInterfaceActivationService', function ($resource) {
return $resource("/r/interface/activate/:active/addr/:address", {}, {
activate:{method:'POST', params:{active:"true", address:'#address'}, isArray:false}
});
});
HTTP call in console:
POST .../r/interface/activate/false/addr/123foobar

Categories

Resources