I have the following code structure and I am trying to maintain the scope of "this" to the current object in the success and error callbacks.
I have tried using Apply function, but I am not sure how to use in my use-case and that's where I need some help.
Here is the code I have :
function navigateToDocumentList(record){
var self= this;
var handoutDocumentList=Ext.create('xxx.view.HandoutsDocumentListPanel');
var navigationView = self.getNavigationView();
navigationView.push(handoutDocumentList);
navigationView.getNavigationBar().show();
navigationView.getNavigationBar().setTitle(record.data.name);
var url = intermountain.constants.HANDOUTS_DOCUMENTS_OF_CATEGORY_SERVICE_URL+record.data.name;
self.makeAJAXCallWIthParams(url,
16000,
self.navigateToDocumentListSuccess,
self.navigateToDocumentListError,
self);
}
function makeAJAXCallWithParams(url, timeout, success, error, callbackObj) {
Ext.Viewport.setMasked({
xtype: 'loadmask',
message: 'Loading ...'
});
Ext.Ajax.request({
url: url,
timeout: 5000,
success: success.apply(callbackObj,[]),// I need to know how to pass the function arguments here as earlier I was just calling it by success and now I need to call it using apply function
failure: failure
});
}
Please let me know if I need to explain the problem better. Any input / hint would be appreciated.
Thanks for your time!
To answer your question about arguments, each function in Javasctript can access a list with all its arguments via the arguments pseudo-parameter:
success: function(){ return success.apply(callbackObj, arguments) }
However, its going to be simpler to use the bind method instead of apply or call.
success: success.bind(callbackObj),
failure: failure.bind(callbackObj)
Related
Let me say, I have a document and it have 10 Ajax function calls to the web method. So, I have update in common for all ajax success so, i used
$(document)ajaxSuccess()
It done the job well.
But, in among the 10 ajax function, I need to ignore only one function's success call to the method or need to handle it different way.
So is there a way to find the caller method details in the ajaxSuccess function and handle.
Thanks in advance.
Happy Coding.
You can use beforeSend option of $.ajax() settings object to set a Boolean flag at jqXHR object and if condition at success callback to check for flag.
setTimeout(function() {
jQuery.ajax({
url: "/path/to/server",
beforeSend: function(jqxhr, settings) {
jqxhr.not = true;
}
})
}, duration);
function commonForAllAjaxSuccess(data, textStatus, jqxhr) {
if (!jqxhr.not) { // do common stuff }
else { // do not do stuff }
}
jQuery(document).ajaxSuccess(commonForAllAjaxSuccess);
Is there any trick to know when the new value is assigned to global variable in callback function in JavaScript.
As I read in here,it is asynchronous , so JavaScript does not wait until the response is received.
I need the new value in my Java code which run JavaScript code in my html page.
There is no trick because you can't write code the way you're trying to write it. You do not want to put the data into a global variable and then try to magically discover when the data is there. That's just not a good way to write async code.
Instead, you need to put the code that uses the result of the async call in the actual callback itself or call some function from the callback and pass it the data.
You don't show your actual code, but here's an example using jQuery Ajax (just for example purposes, you can do this with any code or library):
$.ajax({
type: "POST",
url: "some.php",
data: { name: "John", location: "Boston" },
success: function(data) {
// the results of the ajax call are here in the data argument
// to this callback function
// you can either use the data here (write any code here that needs to use it)
// or you can call some other function and pass it the data
}
});
No. There is no direct possibility.
One possible solution is implementing an observer-pattern or using something like backbone, where models trigger events for changes of state.
Another possible solution is, working with futures or promises. Q gives a possible approach.
The code that needs to access that variable has to be within the callback; else the variable would not have been assigned the value yet.
So you need to trigger the Java code from within the callback. Tough to provide an answer on how to do that without more information.
var callbackFunction = function(arg, callback) {
if ('an error') {
callback(new Error('error text'));
}
else {
// set the global variable
callback(null, 'result');
}
};
var callingFunction = function() {
callbackFunction('arg', function(err, result) {
if (!err) {
// Global variable is set
// Trigger call to Java
}
});
};
You can define yor global variable as object instanse:
var globalVar = {
_val: null,
changed: function () {
alert(1);
},
setValue: function(val) {
_val = val; this.changed();
},
getValue: function() {
return _val;
}
};
Use setValue and getValue to set and get a value of ur global variable:
globalVar.setValue(45); // will set the value and throw an alert box.
globalVar.getValue(); // will return 45
So u can just init 'changed' prop with ur own function and it will be fired if 'setValue' called
How can I use setTimeout() in a Backbone model?
I have the next code:
var ContentModel = Backbone.Model.extend({
URL: "http://localhost/example.php",
requestType: "POST",
dataType: "json",
data: "", //Set the value outside the model
startSend: function (Data) {
//
},
reply: function (Data) {
var dataJson = eval(Data);
console.log(dataJson);
setTimeout(this.ajaxRequest(),4000);
},
problems: function (Data) {
//
},
ajaxRequest: function () {
$.ajax({
async:true,
type: this.requestType,
dataType: this.dataType,
url: this.URL,
data: this.data,
beforeSend:this.startSend,
success: this.reply,
timeout:4000,
error:this.problems
});
}
});
Alternatively I have tried:
setTimeout(function(){
//ajax code
},4000);
But the result is the same. setTimeout() don't work. The request only run once.
A couple of things are amiss. First off, this line:
setTimeout(this.ajaxRequest(),4000);
Should be:
setTimeout(this.ajaxRequest, 4000);
The first line of code executes the ajaxRequest function and passes the result (which is undefined) to setTimeout. That means the ajaxRequest function will execute once, but too soon. The latter line does what you want, which is to pass the function itself to setTimeout, and ajaxRequest will be called 4 seconds later.
But that's not quite enough. When the ajaxRequest function is executed, the value of this context is incorrect. When you called setTimeout, the context of the callback is set to window. You can verify this by console.log(this) in the callback function.
To fix it, you need to bind the context of the function. Since you're using Backbone, you've also got underscore.js already loaded. Using _.bind oughta do it:
setTimeout(_.bind(this.ajaxRequest, this), 4000);
Edit:
Come to think of it, there might be another problem. When the ajax call succeeds or fails, the reply or problems functions may suffer from the same loss of context as ajaxRequest did. But if there is, it's easily fixed.
Instead of calling _.bind on those too, the simplest way is to call _.bindAll in your Backbone model constructor.
initialize: function() {
_.bindAll(this, 'ajaxRequest', 'reply', 'problems');
}
When you call _.bindAll, underscore guarantees that every time any of the listed methods of your model is called, the this context variable points to the model itself, unless specifically bound to something else.
You don't need to do anything special to use setTimeout with backbone. Check the scope of this in your reply function. My guess it that this.ajaxRequest() isn't in scope.
You have to use setInverval instead.
setInterval(this.ajaxRequest, 4000);
setTimeout Triggers the function once.
setInterval Triggers each n ms.
var interval = setInterval(this.ajaxRequest, 4000);
clearInterval used to clear setInterval.
clearInterval(interval);
Or pass the context parameter on your ajax:
$.ajax({
...
context: this,
...
});
Dear All,
I'm using dojo.declare to create classes in JavaScript. In one of the methods, I've an AJAX request. In the load method of that request, I need to execute certain methods.These methods are actually methods of the class that was created using dojo.declare. I tried to execute the method using this. But it gave me method not found error. So I used dojo.hitch(this,testMethod) to invoke it. It worked fine. Now the problem is I've lot of other methods also inside testMethod() which internally calls other methods of my JavaScript class. It is really a pain to have dojo.hitch() everywhere. Is there any work around for this.
dojo.declare("TestClass",null,{
getData:function(url){
dojo.xhrGet({
url:url,
load: function (response){
dojo.hitch(scope of the current object,testMethod(response))
},
error:function(){
}
});
},
testMethod:function(response){
//calls testMethod2. I think I can use dojo.hitch(this,testMethod3) to call it.
//but I wanted to avoid doing it every time.
},
testMethod2:function(){
//calls testMethod3
},
testMethod3:function(){
//can call other methods.
}
});
It seems like that execution scope was lost in this code:
load: function (response){
dojo.hitch(this,testMethod(response))
},
I made small changes in your code. Now it should work properly.
dojo.declare("TestClass",null,{
getData:function(url){
dojo.xhrGet({
url:url,
load: dojo.hitch(this,this.testMethod),
error:function(){
}
});
},
testMethod:function(response){
this.testMethod2();
},
testMethod2:function(){
this.testMethod3();
},
testMethod3:function(){
//can call other methods.
}
});
This is a typical context problem. You are passing an uncontexted function as a property of a configuration hash, which is passed as argument to dojo.xhrGet.
dojo.hitch is exactly the right construct to add a context to a function. Another way is to simply use a closure. Is there any reason why you can't do:
var me = this;
dojo.xhrGet({
url:url,
load: function(response) {
me.testMethod(response);
}
});
Try doing it like this:
dojo.xhrGet({
url:url,
load: dojo.hitch(this, "testMethod"),
error:function(){
}
});
Your way worked as well, but it saves you a few bytes and is just cleaner to use the method name as a string. Hitch will automatically pass the arguments for you.
I have written a function that retrieves a html template, then binds data using jQuery.tmpl. I think it's fairly neat and tidy and encapsulates what I need and provides me a reusable function. My question however is can it be improved.
My main concern is what if the $.get method fails, and also how the callBack function is executed.
function Bind(templateURL, templateData, templateTarget, callBack){
var req = $.get(templateURL);
req.success(function(templateHtml) {
$(templateTarget).html(''); //clear
$(templateHtml).tmpl(templateData).appendTo(templateTarget); //add deal
callBack();
});
}
You can pass the result of tmpl() directly to html() to clear your target container and append the new content at the same time. You can also chain the result of $.get() into your success handler to avoid using a local variable:
function Bind(templateURL, templateData, templateTarget, callBack)
{
$.get(templateURL).success(function(templateHtml) {
$(templateTarget).html($(templateHtml).tmpl(templateData));
callBack();
});
}
If $.get() fails, nothing will happen since you do not register an error handler. What that handler would do is up to you, but you might want to display an appropriate message in an alert box or somewhere on the page.
Your second concern is less clear. As it stands, callBack will only be called on success, and without arguments.
You can use $.ajax to assign and error calback. ex:
var jqxhr = $.ajax({ url: "example.php" })
.success(function() { alert("success"); })
.error(function() { alert("error"); })
Check the api http://api.jquery.com/jQuery.ajax/