how to determine when a request in completed in mootools? - javascript

I am new to moootools and I am creating a Template class,This is my code -
var Template = new Class({
Singleton : true,
template : '',
/* gets the component type template */
get : function(componentType){
var tplUrl = Core.getUrl('backend') + 'response/' + componentType + '/get_template.php',
that = this,
request = new Request({url: tplUrl, method : 'get',onSuccess : function(responseText){
that.template = responseText;
return that;
}}).send();
}
});
What I want to do is this :
var tpl = new Template();
tpl.get('component').setTemplateData({name:'yosy'});
The problem is when I am calling this code :
var tpl = new Template();
console.log( tpl.get('component') );
I am not getting my current Template object,I am getting is 'undefined'.
How I can make this chainable?

You are making an asynchronous call inside the get function. The request may take 100ms, 1s or 10s and by the time the get function finishes and returns, the request will still be pending. Instead what you need to do is, pass a callback function to get and call that on success.
get: function(componentType, successCallback) {
var request = new Request({
..,
onSuccess: successCallback
}).send();
}
Note that you are not returning anything from the get function. One example way to invoke this would be:
tpl.get('component', function(responseText) { alert(responseText); });

Your get function is missing a return value. If you want functions to chain you should return the object itself:
get : function(componentType){
var tplUrl = Core.getUrl('backend') + 'response/' + componentType + '/get_template.php',
that = this,
request = new Request({url: tplUrl, method : 'get',onSuccess : function(responseText){
that.template = responseText;
return that;
}}).send();
return this;
}

Related

jQuery object, inconsistent global variables and AJAX call

I'm looking to get what I thought would be a simple script to run an AJAX call and keep various values stored to an object, but I cannot get the globals to remain consistent the way I would expect.
I've gone around in circles trying what I think is everything. As soon as I put the AJAX call in I can't get it to play nicely with the global variables. The process value is always false that way and the content never loads in.
ExtContent = function(){
var self = this;
this.init = function() {
self.output = null;
self.process = false;
};
this.request = function(url){
$.ajax({
type : 'GET',
timeout : 10000,
dataType : 'html',
url : url,
passself : self,
success : function(response){
this.passself.setoutput(response);
},
error : function(req,response){
if(response==='error'){
self.error=req.statusText;
}
}
});
};
this.setoutput = function(data){
this.output = data;
this.process = true;
};
this.returnprocess = function(){
return self.process;
};
this.returnoutput = function(){
return self.output;
};
self.init();
};
<div id="holder"></div>
loadcontent = new ExtContent();
loadcontent.request('/test.html');
if(loadcontent.returnprocess()){
$('#holder').before(loadcontent.returnoutput());
}else{
$('#holder').before('FAILED');
}
I can't get the process to be true and the content to be stored in output.
Thanks.
Despite wrapping everything as a class/object, the jQuery $.ajax call is still an asynchronous operation. basically "You have ordered a pizza, then try to eat it before it arrives".
i.e. this orders it:
loadcontent.request('/test.html');
and this tries to eat it immediately:
if(loadcontent.returnprocess()){
The call to setoutput (i.e. the "Pizza delivery") happens long after these operations complete.
You need to add event handler properties to your class, or use deferreds+promises to wait for the data to arrive.
To use promises, just return the $.ajax result from request:
this.request = function(url){
return $.ajax({
type : 'GET',
timeout : 10000,
dataType : 'html',
url : url,
passself : self,
success : function(response){
this.passself.setoutput(response);
},
error : function(req,response){
if(response==='error'){
self.error=req.statusText;
}
}
});
};
and use it like this:
loadcontent.request('/test.html').done(function(){
if(loadcontent.returnprocess()){
$('#holder').before(loadcontent.returnoutput());
}else{
$('#holder').before('FAILED');
}
});
Or if you setup the return values correctly inside request:
loadcontent.request('/test.html').done(function(){
$('#holder').before(loadcontent.returnoutput();
}).fail(function(){
$('#holder').before('FAILED');
});
Maybe this can help you
this.setoutput = function(data){
// 'this' here, is refering 'setoutput' function, not ExtContent,
// so ExtContent.process != ExtContent.setoutput.process
// this.output = data;
// this.process = true;
self.output = data;
self.process = true;
};

Functions within a loop using requirejs

I'm having an issue with calling functions within a loop across different modules using requirejs. The function call within the loop resides in module A and executes a function in module B that fires off an Ajax request using jQuery. Each iteration of the loop fires off a different request with different arguments being passed to module B's function that fires off the Ajax request. When the success function of the Ajax request executes, I find that all my argument values are always the values of the last Ajax call made, for all 4 separate Ajax calls.
I've done some googling and it sounds like this is a pretty common problem when executing a function within a loop. The fix tends to be to break out the function call into a different function, creating a different scope. Since my loop and Ajax calls are in 2 different modules I had assumed this would solve that issue, however it still persists.
I've tried some solutions in other stack overflow posts like:
JSlint error 'Don't make functions within a loop.' leads to question about Javascript itself and How to pass parameter to an anonymous function defined in the setTimeout call? without success. Anyone have any idea?
Sample code for loop module A:
define(["mpos"],
function(mpos){
var monitor = {
startMonitoring : function(poolObj){
// Start Monitoring
$.each(mpos.msgs, function(action,callback){
poolObj.action = action;
mpos.sendApiRequest(poolObj,action,callback);
});
}
};
return monitor;
}
);
Sample code for Ajax module B - this module is referenced as mpos in module A
define(["mule","constants"],
function(mule,constants){
var mpos = {
sendMessage : function(postData,callback,$poolOut){
return $.ajax({
'type':'post',
'url':constants.URLS.proxy,
'data':{'url':postData},
success : function(data){
// if we have $poolOut we know this is a mpos call
if($poolOut != undefined){
var keys = Object.keys(data);
// add poolOut to data
data.poolOut = $poolOut;
var poolObj = $poolOut.data('poolObj');
if(poolObj){
var action = poolObj.action;
console.log(poolObj,action);
if(action){
if(action == "getuserstatus"){
mule.registerPool(poolObj);
}
} else {
log.error("No action on poolObj while attempting to calculate the need for a registerPool call");
}
}
}
// parse data
callback.apply(this, data);
},
error : function(x,h,r){ ... },
dataType : 'json'
});
},
sendApiRequest : function(poolObj,action,callback){
var url = poolObj.url + '&page=api&action=' + action;
var $poolOut = constants.cache.monitorOutput.find('.pool-out.' + poolObj.id);
var dfd = mpos.sendMessage(url,callback,$poolOut);
$.when(dfd).always(function(){
var refreshTimer = setTimeout(function(){
if(constants.state.monitorEnabled){
mpos.sendApiRequest(poolObj, action, callback);
}
}, poolObj.refreshRate);
});
},
msgs : {
"getuserstatus" : function(data){ ... },
"getpoolstatus" : function(data){ ... },
"getuserworkers" : function(data){ ... },
"getuserbalance" : function(data){ ... }
}
};
return mpos;
}
);
Thanks!
NOTE: I am assuming that $poolOut.data('poolObj') is being used to find the poolObj instance passed in the call to startMonitoring, and will return the same instance each time.
You state, "Each iteration of the loop fires off a different request with different arguments being passed to module B's function that fires off the Ajax request."
This statement is not correct. Each iteration fires off a different request with the first argument poolObj being the same in each iteration.
In your .each iteration, you are overwriting the value of poolObj.action before each call to sendApiRequest.
In the AJAX success handler, which is likely invoked after all iterations have completed, the value of poolObj.action will have the value you set it to in the last iteration.
To solve this, I think you need to pass action as a parameter to sendMessage, too, so that a separate value is being stored in the closure for each function call.
var mpos = {
sendMessage : function(postData,action,callback,$poolOut){
return $.ajax({
'type':'post',
'url':constants.URLS.proxy,
'data':{'url':postData},
success : function(data){
// if we have $poolOut we know this is a mpos call
if($poolOut != undefined){
var keys = Object.keys(data);
// add poolOut to data
data.poolOut = $poolOut;
var poolObj = $poolOut.data('poolObj');
if(poolObj){
// action is not guaranteed to be the same as poolObj.action here,
// since poolObj.action may have changed since this function was first called
console.log(poolObj,action);
if(action){
if(action == "getuserstatus"){
mule.registerPool(poolObj);
}
} else {
log.error("No action on poolObj while attempting to calculate the need for a registerPool call");
}
}
}
// parse data
callback.apply(this, data);
},
error : function(x,h,r){ ... },
dataType : 'json'
});
},
sendApiRequest : function(poolObj,action,callback){
var url = poolObj.url + '&page=api&action=' + action;
var $poolOut = constants.cache.monitorOutput.find('.pool-out.' + poolObj.id);
var dfd = mpos.sendMessage(url,action,callback,$poolOut);
$.when(dfd).always(function(){
var refreshTimer = setTimeout(function(){
if(constants.state.monitorEnabled){
mpos.sendApiRequest(poolObj, action, callback);
}
}, poolObj.refreshRate);
});
},
msgs : {
"getuserstatus" : function(data){ ... },
"getpoolstatus" : function(data){ ... },
"getuserworkers" : function(data){ ... },
"getuserbalance" : function(data){ ... }
}
};

AngularJS : having problems with $scope,factory returns

Im learning AngularJs.
And I find my self enjoying it, But im stuck with this code
my controller
$scope.getQuestionaires = function(){
var formdata = $scope.formdata;
var items = parseInt(formdata.items);
var num_letter = parseInt(formdata.num_letter);
var num_missing_letter = parseInt(formdata.num_missing_letter);
var send_data = {
api_type: 'select',
tb_name: 'tb_spelling',
tb_fields: false,
tb_where: false,
tb_others: "LIMIT "+items
};
return factory.getRecords(send_data);
}
my factory
factory.getRecords = function(data) {
return $http.post('models/model.php', {
params: data
}).then(function(response) {
records = response.data;
return records;
});
};
Situation : When I console.log($scope.getQuestionaires), It returns
function (b,j){var
g=e(),i=function(d){try{g.resolve((b||c)(d))}catch(e){a(e),g.reject(e)}},o=function(b){try{g.resolve((j||
d)(b))}catch(c){a(c),g.reject(c)}};f?f.push([i,o]):h.then(i,o);return
g.promise} controllers.js:307 function (a){function b(a,c){var
d=e();c?d.resolve(a):d.reject(a);return d.promise}function d(e,f){var
j=null;try{j=(a||c)()}catch(g){return b(g,!1)}return
j&&j.then?j.then(function(){return b(e,f)},function(a){return
b(a,!1)}):b(e,f)}return this.then(function(a){return
d(a,!0)},function(a){return d(a,!1)})} controllers.js:307
[Object, Object, Object, Object]
Question : My problem is that i only want the array of objects, how can i do that? I think theres a lot i got to improve about my code...I need help :)
Thx
====================================
Fixed
Thx to Chandermani's answer,
Got it!
My controller
$scope.createTest = function(){
$scope.getQuestionaires();
}
/*question getter*/
$scope.getQuestionaires = function(id,question){
/*send_data here*/
var records = factory.getRecords(send_data);
records.then(function(response){
$scope.questionaires = response.data;
});
}
My factory
factory.getRecords = function(data) {
return $http.post('models/model.php', {
params: data
});
};
The method getQuestionaires returns response for your $http post method which is a promise and not the actual data, since the call is async.
Change the method getRecords to
factory.getRecords = function(data) {
return $http.post('models/model.php', {
params: data
});
};
When you call the method getQuestionaires do something like
$scope.getQuestionaires().then(function(response){
//access response.data here
});
Try to understand the async nature of such request. If you ever call async methods within your own functions you can access the response by either returning the promise or provide a callback as a argument to the function.

JavaScript OOP - Not able to set the public value from Ajax call inside a Class structure

i faced issue while writing a class specially for handling Ajax calls & its response.
Purpose of below code : Based on user records exist in database, i need to set the flag "isPersonalDivRequiredFlag" for further use.
// New ajax request class
function ajaxRequestHandler(){
this.needOutPutInJSON = 0;
this.url = "/libraries/ajaxHelper.php";
this.requestType = "POST";
this.isPersonalDivRequiredFlag = 0;
};
// Methods written for Class ajaxRequestHandler
ajaxRequestHandler.prototype = {
sentRequest : function(userData, typeID){
var options = {type: this.requestType, context: this, url: this.url, data: { data: userData, type: typeID }};
if(this.needOutPutInJSON){
options.dataType = "json";
}
// Check whether user want to see the response
options.success = function(rec){
if(rec == "1"){
this.isPersonalDivRequiredFlag = 1;
}
};
//Jquery Ajax
$.ajax(options);
},
enableJSONoutput : function(){
this.needOutPutInJSON = 1;
},
getFlagValue : function(){
return this.isPersonalDivRequiredFlag;
},
setFlagValue : function(){
console.log('Setflag Func called.');
this.isPersonalDivRequiredFlag = 1;
}
};
And i use the code as below.
var newRequest = new ajaxRequestHandler();
console.log('Before change [Value of isPersonalDivRequiredFlag variable] : ' + newRequest.getFlagValue()); // Output 0
newRequest.sentRequest({}, "recordExist");
console.log('After change [Value of isPersonalDivRequiredFlag variable] : ' + newRequest.getFlagValue()); // Output 0
And when i set the flag "isPersonalDivRequiredFlag " to 1 inside the Success method of Ajax call but its unable to retain this value when it will be accessed through its own method "getFlagValue" function.
The whole piece of code will work fine if i remove Ajax call function & made it a normal prototype method. So i know the cause but not able to find any solution :(
what the things i tried already?
I found some techniques people suggested while Google it over internet.
a) Used this configuration inside Ajax call but no luck :(
context:this
b) inside Success method :
var myclass = this;
And called the prototype function as below
myclass.setFlagValue();
but no luck :(

Using jQuery, how can I store the result of a call to the $.ajax function, to be re-used?

Thanks for reading this.
I imagine this is really a javascript question, and my title probably does not get at the heart of what I am trying to do, but I want to store the result of my ajax request in a global variable. This would allow me to test the var before making the ajax call...and avoid repeated ajax calls for the same data. I need to be able to pass the variable name from the click event down through the populateSelect function into the ajaxCall function.
It seems like I could pass a function as a parameter, but I have not been able to make that work.
I like to include working examples in my questions, but in this case the latency in the call to the server is part of the problem.
Thanks
$('#getSelectOptions').bind("click", function() {
populateSelect(this);
});
function populateSelect(whatWasClicked) {
var thisSelect = $(whatWasClicked).parents("div").find("select") ;
var before = function() { $(loading).show() ; } ;
var complete = function() { $(loading).hide() ; } ;
var data = {'_service' : 'myService', '_program' : 'myProgram' } ;
var error = function(){alert("Error"); } ;
var success = function(request) { $(thisSelect).html(request) ; };
var waitTime = 20000 ;
ajaxCall(thisSelect, waitTime, before, complete, data, success, error ) ;
}
function ajaxCall(elementToPopulate, waitTime, whatToDoBeforeAjaxSend,
whatToDoAfterAjaxSend, dataToSendToTheServer,
whatToDoAfterSuccess, whatToDoAfterError) {
$.ajax({
type: "post",
url: "http://myURL/cgi-bin/broker",
dataType: "text",
data: dataToSendToTheServer,
timeout: waitTime,
beforeSend: whatToDoBeforeAjaxSend,
error: whatToDoAfterError(request),
success: whatToDoAfterSuccess(request)
});
}
EDIT Further education in how to write a good question... I should have mentioned that I call populateSelect to populate multiple selects..so I need way to reference the results for each select
jQuery has a $.data method which you can use to store/retrieve items related to any element on the page.
//e.g. create some object
var inst = {};
inst.name = 'My Name'
var target = $('#textbox1');
//save the data
$.data(target, 'PROP_NAME', inst);
//retrieve the instance
var inst = $.data(target, 'PROP_NAME');
It looks like in the example you gave, you only have one type of AJAX request, POSTed to the same URL with the same data every time. If that's the case, you should just need something like :
var brokerResponse = null; // <-- Global variable
function populateSelect(whatWasClicked) {
var thisSelect = $(whatWasClicked).parents("div").find("select") ;
if (!brokerResponse) { // <-- Does an old response exist? If not, get one...
var before = function() { $(loading).show() ; } ;
var complete = function() { $(loading).hide() ; } ;
var data = {'_service' : 'myService', '_program' : 'myProgram' } ;
var error = function(){alert("Error"); } ;
var success = function(request) { // <-- Store the response before use
brokerResponse = request;
$(thisSelect).html(brokerResponse);
};
var waitTime = 20000 ;
ajaxCall(thisSelect, waitTime, before, complete, data, success, error ) ;
}
else { // <-- If it already existed, we get here.
$(thisSelect).html(brokerResponse); // <-- Use the old response
}
}
If you have multiple possible items for whatWasClicked which each need a different AJAX response cached, then you need to have some string with which to identify whatWasClicked, and use that to store multiple values in your global variable. For example, if you have a unique id on whatWasClicked, this would work:
var brokerResponse = {}; // Global variable is a simple object
function populateSelect(whatWasClicked) {
var whatWasClickedId = $(whatWasClicked).attr('id'); // Get the unique ID
var thisSelect = $(whatWasClicked).parents("div").find("select") ;
if (!brokerResponse[whatWasClickedId]) { // Check that ID for a response
var before = function() { $(loading).show() ; } ;
var complete = function() { $(loading).hide() ; } ;
var data = {'_service' : 'myService', '_program' : 'myProgram' } ;
var error = function(){alert("Error"); } ;
var success = function(request) {
brokerResponse[whatWasClickedId] = request; // Using ID
$(thisSelect).html(brokerResponse);
};
var waitTime = 20000 ;
ajaxCall(thisSelect, waitTime, before, complete, data, success, error ) ;
}
else {
$(thisSelect).html(brokerResponse[whatWasClickedId]); // Etc...
}
}
JavaScript's scoping is such that if you just declared a global variable, you should be able to access it from within the ajax success function and the click function as well.
var _global_holder = null;
$('#getSelectOptions').bind("click", function() {
if(_global_holder==null) { whatever }
populateSelect(this);
});
function populateSelect(whatWasClicked) {
if(_global_holder !== null) {
whatever
} else { whatever else }
ajaxCall(thisSelect, waitTime, before, complete, data, success, error ) ;
}
function ajaxCall(elementToPopulate, waitTime, whatToDoBeforeAjaxSend,
whatToDoAfterAjaxSend, dataToSendToTheServer,
whatToDoAfterSuccess, whatToDoAfterError) {
...
}

Categories