How to get a dojo handler to return value to calling function?
getContributor: function(userId) { var contributor; var args = { searchField: "userId", searchTerm: userId }; var handler = { success: dojo.hitch(this, function(responseObj) { contributor = responseObj.elements[0]; }), error: function(errorObj) { console.log(errorObj.message); } }; var serviceResponseHandler = new com.ibm.team.repository.web.transport.ServiceResponseHandler(handler, "success", "error"); com.ibm.team.repository.web.client.internal.AdminClient.getContributors(args, serviceResponseHandler); return contributor; // undefined
}
2 answers
First you should be aware what asynchroneous means.
As soon as you start an async process it's like a new Thread.
Method A --> AsyncMethodA (Cant return to Method A because it isnt the same "process-Scope"[probably a wrong word])
So, if you wanna use async methods you'll have to adapt their behaviour.
And thats, where the responseHandler comes into the play.
All 3 calls will now land in the same method.
How you will handle it, its your choice.
Method A --> AsyncMethodA --> ResponseMethodA
Method A --> AsyncMethodA --> ResponseMethodA
Method A --> AsyncMethodA --> ResponseMethodA
If you NEED a return value, use a synchroneous get.
Problem:
main: function(){
//test NEVER gets the value
var test = this.getContributor("blabla");
}
getContributor: function(userId) {
var contributor; //1: NOT THE SAME CONTEXT
//var contributor2 //2: Keep the same context
var args = {
searchField: "userId",
searchTerm: userId
};
//var self = this; //2: Here we give the method a possibility to keep the scope
var handler = {
success: dojo.hitch(this, function(responseObj) {
contributor = responseObj.elements[0]; //1: AS THIS
this.contributor = ... //1: This would be the same var as outside
//self.contributor2 //2: This is now the same Object
}),
error: function(errorObj) {
console.log(errorObj.message);
}
};
var serviceResponseHandler = new com.ibm.team.repository.web.transport.ServiceResponseHandler(handler, "success", "error");
com.ibm.team.repository.web.client.internal.AdminClient.getContributors(args, serviceResponseHandler);
return contributor; // undefined //1: This stays undefined
return contributor2 //2: Still not working, because it will not be setted when it's returned
//2: You can check this if you'll add a wait/sleep method before the return
}
Solution:
var transactionsInAction = null;
var responseStorage = null;
//A little idea how to handle async calls
main: function(){
this.transactionsInAction = 0;
this.responseStorage = [];
this.getContributor("blabla1");
this.getContributor("blabla2");
this.getContributor("blabla3");
}
dataResolved: function(contributor, transactionId){
this.responseArrays[transactionId] = contributor;
//this.responseArrays.push(contributor); //Without transactionId
this.transactionsInAction--;
if(this.transactionsInAction < 1){ //No transactions in action
this.doWhatYouWantOrNeed();
}
}
getContributor: function(userId) {
var args = {}; //I keep it blank to save space
//Better would be to use deferred but hitch works too, to keep the scope
var handler = {
success: dojo.hitch(this, function(responseObj) {
var transactionId = this.transactionsInAction; //This could help to keep track which data are when loaded but not needed.
this.dataResolved(responseObj.elements[0], transactionId); //This sends the response to the given method
}),
error: function(errorObj) {
}
};
this.transactionsInAction++;
var serviceResponseHandler = new com.ibm.team.repository.web.transport.ServiceResponseHandler(handler, "success", "error");
com.ibm.team.repository.web.client.internal.AdminClient.getContributors(args, serviceResponseHandler);
}
getContributor: function(userId) { var contributor; var args = { ... }; success: dojo.hitch(this, function(responseObj) { contributor = responseObj.elements[0]; }), error: function(errorObj) { console.log(errorObj.message); } }; var serviceResponseHandler = new com.ibm.team.repository.web.transport.ServiceResponseHandler(handler, "success", "error"); com.ibm.team.repository.web.client.internal.AdminClient.getContributors(args, serviceResponseHandler); while (!contributor) { // wait until outer var get a value? } return contributor; }Thanks in advance.
Comments
Hello Mister Servizi,
It sure worth a try!
The downside on this code is, that it'll block the whole Process till the wished data (contributors) are retrieved.
But why keep it sequentially? Instead of A -> WAIT -> B
Why not going over a third method? A -> A-helper -> B
This way it would be non blocking code.
But if you just need some Field Values (That's why I'm guessing you want to use the return) It might work the way you suggested.
Another Idea could be to work with deferred.
getContributorData: function(userId) {
var deferred = new dojo.Deferred();
//Your code
//Maybe its possible to directly return from the succees method since hitch keeps the same context.
//return responseObj.elements[0];
return deferred;
}
getContributor{
var deferred = getContributorData(); deferred.then(function(value){ // Do something on success. }, function(error){ // Do something on failure. });
}