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

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.

Related

Recall $resource factory within interception

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.

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

Is it possible to use repeating params in ngResours query

I'm using Angular with ngResource and i've got an api url:
GET http://my.com/rest/items?inState=TRANSIENT&inState=FINAL
How could I do query with two (not uniq) params 'inState'?
This is my Resource factory:
.factory('Resource', function ($resource, REST_URL) {
return {
items: $resource(REST_URL + 'rest/items',
{},
{
get: {method: "GET", params: {inState: '#inState'}}
})
};
})
And this is the way I'm call it:
//GET http://my.com/rest/items?inState=TRANSIENT
Resource.items.get({inState: 'TRANSIENT'}, function (data) {
//...
}, function (responce) {
//...
});
This is works but the problem is in how I'm send params - as object: {inState: 'TRANSIENT'}
I cannot write something like
{inState: 'TRANSIENT', inState: 'FINAL'}
beacuse of fields must be uniq
P.S. I know that it may be done with $http.
That's how to do this:
{inState: ['TRANSIENT', 'FINAL']
Example:
//GET http://my.com/rest/items?inState=TRANSIENT&inState=FINAL
Resource.items.getHistory({inState: ['TRANSIENT', 'FINAL']}, function (data) {
//...
}, function (responce) {
//...
});
Not sure if you have control over what is consuming the parameters, but if you do you could try passing the parameters as an object with an array of objects in it, like this:
{ states : [{inState : 'TRANSIENT'}, {inState : 'FINAL'}]}
Then just iterate through the states array and check each inState property.

Backbone fetch success and error function issue

I've a fetch method on a collection. The callback function success and error is never called but the fetch happens correctly and fill the collection. It seems very strange.
var TweetsCollection= new Tweets();
TweetsCollection.fetch({
success:function (tweets){<---never called
alert("ok");
},
error:function(c){<---never called
alert("ko");
}
});
console.log(TweetsCollection);<---- collection correctly filled
and this is the fetch methof od TweetsCollection:
fetch: function(options) {
var collection = this;
var params = {
user_id: this.query,
page:this.page
};
cb.__call(
"statuses_userTimeline",
params,
function (reply) {
// console.log(reply);
collection.reset(reply);
// return reply;
}
);
}
You don't have to override the fetch method.
If you want to add extra logic to the sync process, you override the sync method.

angular.js ui + bootstrap typeahead + asynchronous call

I'm using typeahead with the angular.js directive but my function to populate the autocomplete makes an asynchronous call and I can't return it to populate the autocomplete. Is there anyway to make it work with this asynchronous call?
Can I assume that you are using the typeahead of Bootstrap 2.x ?
If so, in the documentation, the description of the source field of typeahead()'s options is this:
The data source to query against. May be an array of strings or a
function. The function is passed two arguments, the query value in the
input field and the process callback. The function may be used
synchronously by returning the data source directly or asynchronously
via the process callback's single argument.
You can definitely pass in an async function as the source attr. The source function could be something like:
function someFunction(query, process) {
someAsyncCall(...query or so... , function(res) { // success callback
process(res);
}, function(err) { // error callback
process(null);
});
}
Update:
If you are using Angular Bootstrap's typeahead, it should be even easier. According to Angular Bootstrap's docs(http://angular-ui.github.io/bootstrap/), you can just return a promise for the typeahead function. Some example from the docs:
$scope.getLocation = function(val) {
return $http.get('http://maps.googleapis.com/maps/api/geocode/json', {
params: {
address: val,
sensor: false
}
}).then(function(res){
var addresses = [];
angular.forEach(res.data.results, function(item){
addresses.push(item.formatted_address);
});
return addresses;
});
};
A simpler one could be:
$scope.getSomething= function(query) {
var promise = $http.get('...some url...', {
params: {
queryName: query
}
});
return promise;
};
Or you can build your own promise:
$scope.getSomething= function(query) {
var deferred = $q.defer();
someAsyncCall(...query or so... , function(res) { // success callback
deferred.resolve(res);
}, function(err) { // error callback
deferred.reject(err);
});
return deferred.promise;
};
Actually, many services like $http are just returning promises when you call them.
More about promise in AngularJS: https://docs.angularjs.org/api/ng/service/$q

Categories

Resources