I am making a ajax call and depending on the result I will swop my img, and fire an alert. Neither of which are happening, but I can't understand why this isn't happening??
var myd = "";
$.ajax({
url:"urlencode.php",
data: data,
type: "POST",
success: function(data) {
myd = $('<span />').html(data).find("#Result").text();
console.log(myd);
if (myd == 'c5:3;'){$(this).attr('src','lightbulboff.png')};
},
error: function (request, status, error)
{
alert(request.responseText);
}
});
The problem is that the this value in your callback is changed; it's now the jqXHR object. The simplest way to fix this is to bind your callback to the current this value:
function(data) {
myd = $('<span />').html(data).find("#Result").text();
console.log(myd);
if (myd == 'c5:3;'){$(this).attr('src','lightbulboff.png')};
}.bind(this)
This will "pre-set" the this value of your callback. Just note that this isn't available in IE8, and so you'd need to shim it. A shim is available here
The other way to fix this is to "save" the current value of this. Something like:
var self = this;
$.ajax(......
success: function(){
myd = $('<span />').html(data).find("#Result").text();
console.log(myd);
if (myd == 'c5:3;'){$(self).attr('src','lightbulboff.png')};
Your callback will "close over" the self variable, and still have access to it when the callback runs.
Related
I have an ajax call inside a .each loop wrapped in a setInterval function.
This handles updating of many divs on a dashboard with just a few lines of code on the html page.
I am worried about server lag vs client side speed. What will happen if the server has not responded with the data before the loop moves on to the next iteration?
So, my question is, can the loop be paused until the success is executed?
Ajax call:
setInterval(function() {
$(".ajax_update").each(function(){
$.ajax({
type: "POST",
dataType: "json",
url: "ajax/automated_update/confirmed_appointments.php",
data: "clinic_id=<? echo $clinic_id ?>&tomorrow=<? echo $tomorrow ?>&"+$(this).data('stored'), // serializes the form's elements.
success: function(data)
{
$(data[0]).html(data[1]);
}
});
});
}, 5000); //5 seconds*
</script>
I have looked into .ajaxComplete() but I dont see how to apply this as a solution.
I have also looked at turning the loop into something that calls itself like:
function doLoop() {
if (i >= options.length) {
return;
}
$.ajax({
success: function(data) {
i++;
doLoop();
}
});
}
But would that not interfere with .each? I dont understand how that would play nice with .each and looping based on my div class.
I just cant figure it out! Any help would be appreciated.
I was able to get .when working with the ajax call, but I dont understand how to make .when do what I need (stop the loop until the ajax call is done).
$(".ajax_update").each(function(){
$.ajax({
type: "POST",
dataType: "json",
url: "ajax/automated_update/confirmed_appointments.php",
data: "clinic_id=<? echo $clinic_id ?>&tomorrow=<? echo $tomorrow ?>&"+$(this).data('stored'), // serializes the form's elements.
success: function(data)
{
$(data[0]).html(data[1]);
}
});
$.when( $.ajax() ).done(function() {
alert("Finished it");
});
});
After thinking about your question a bit, perhaps a good solution would be to put an event in place that would trigger a new set of updates with a minimum time between your dashboard updates. This would ensure that all your updates process, that we do wait a minimum time between updates and then trigger the update cycle once again. Thus if you DO encounter any delayed ajax responses you do not try another until the previous one has all completed.
I have not fully tested this code but is should do what I describe:
//create a dashboard object to handle the update deferred
var dashboard = {
update: function (myquery) {
var dfr = $.Deferred();
$.ajax({
type: "POST",
dataType: "json",
url: "ajax/automated_update/confirmed_appointments.php",
data: "clinic_id=<? echo $clinic_id ?>&tomorrow=<? echo $tomorrow ?>&" + myquery,
success: dfr.resolve
});
return dfr.promise();
}
};
//create a simple deferred wait timer
$.wait = function (time) {
return $.Deferred(function (dfd) {
setTimeout(dfd.resolve, time);
});
};
// use map instead of your .each to better manage the deferreds
var mydeferred = $(".ajax_update").map(function (i, elem) {
return dashboard.update($(this).data('stored')).then(function (data, textStatus, jqXHR) {
$(data[0]).html(data[1]);
});
});
//where I hang my dashboardupdate event on and then trigger it
var mydiv = $('#mydiv');
var minimumDashboardUpdate = 5000;
$('#mydiv').on('dashboardupdate', function () {
$.when.apply($, mydeferred.get())
.then(function () {
$.when($.wait(minimumDashboardUpdate)).then(function () {
mydiv.trigger('dashboardupdate');
});
});
});
mydiv.trigger('dashboardupdate');
I have a form in my page. When a user clicks a button if have no problem this code must navigate my Tile page. I am taking this problem:Uncaught TypeError: Cannot read property 'navTo' of undefined.
This my code:
onPressGonder: function (evt) {
var sURL = "xxxxxx";
$.ajax({
url: sURL,
dataType: "json",
success: function(data) {
if (data.ResultCode === 7) {
sap.m.MessageToast.show("Error:" +data.Alerts[0].Message+"") ;
} else {
sap.m.MessageToast.show("Login succesfull.");
sap.ui.core.UIComponent.getRouterFor(this).navTo("Tile");
}
}
});
}
You are having a scope problem. The function provided as a success callback is a anonymous function called later on by jQuery.ajax. Therefore it is NOT a method of your controller and thereby does not know this. By default (as in your anonymous function) this refers to the window object. So what your basically doing is:
sap.ui.core.UIComponent.getRouterFor(window).navTo("Tile");
And the window object obviously does not have a router or a navTo method ;)
The easiest workaround is to make this available via the closure scope as follows:
onPressGonder: function (evt) {
var sURL = "xxxxxx",
that = this;
$.ajax({
url: sURL,
dataType: "json",
success: function(data) {
if (data.ResultCode === 7) {
sap.m.MessageToast.show("Error:" +data.Alerts[0].Message+"") ;
} else {
sap.m.MessageToast.show("Login succesfull.");
sap.ui.core.UIComponent.getRouterFor(that).navTo("Tile");
}
}
});
}
Another probably more elegant solution is to use the context property of jQuery.ajax. It will ensure that any ajax callback will be executed with the provided context (meaning whatever you pass as a context will be referred to as this inside your callbacks):
$.ajax({
...
success: function(data) {
...
sap.ui.core.UIComponent.getRouterFor(this).navTo("Tile");
},
context: this
});
I have a .js class named Widget.js
In widget.js class I am initiating a errors.ascx control class that has a JS script function "GetErrors()" defined in it.
Now, when I call GetErrors from my widgets.js class it works perfectly fine.
I have to populate a few controls in widgets.js using the output from GetErrors() function.
But the issue is that at times the GetErrors() takes a lot of time to execute and the control runs over to my widgets class. and the controls are populated without any data in them.
So the bottom line is that I need to know the exact usage of the OnSuccess function of Jquery.
this is my errors.ascx code
var WidgetInstance = function () {
this.GetErrors = function () {
$.ajax({
url: '/Management/GetLoggedOnUsersByMinutes/',
type: 'GET',
cache: false,
success: function (result) {
result = (typeof (result) == "object") ? result : $.parseJSON(result);
loggedOnUsers = result;
}
});
},.....
The code for the Widgets.js file is
function CreateWidgetInstance() {
widgetInstance = new WidgetInstance();
widgetInstance.GetErrors();
}
now I want that The control should move from
widgetInstance.GetErrors();
only when it has produced the results.
any Help???
You can use jQuery Deferreds. $.ajax() actually returns a promise. So you can do the following:
var WidgetInstance = function () {
this.GetErrors = function () {
return $.ajax({
url: '/Management/GetLoggedOnUsersByMinutes/',
type: 'GET',
cache: false
});
},.....
Then you can process the results like so...
widgetInstance.GetErrors().done(function(result){
//process the resulting data from the request here
});
Hi Simply use async:false in your AJAX call.. It will block the control till the response reaches the client end...
var WidgetInstance = function () {
this.GetErrors = function () {
$.ajax({
url: '/Management/GetLoggedOnUsersByMinutes/',
type: 'GET',
cache: false,
async: false,
success: function (result) {
result = (typeof (result) == "object") ? result : $.parseJSON(result);
loggedOnUsers = result;
}
});
},.....
I did a simple solution for this..
I just called my populating functions in the onSuccess event of the GetErrors() of my control and everything worked perfectly..
I have an old code which is dependant on JQuery 1.3.2 that uses the following ajax call
function ChangeContent(url, somepageobject) {
var xhrobj = $.ajax({
url: url,
context: somepageobject,
callback: doFurtherStuff,
success: function(data) {
somepageobject.html($(data));
this.callback.call(this.context[0], data, "ok"); // >> Code breaks here
}
});
return xhrobj;
}
Problem with the code above is that this.callback is null when I upgraded to JQuery 1.8.1, most importantly the ChangeContent function is being used in different places and is outside my control (its used as as an API for external users...etc). An example of the usage of the above is like this:
xhr_object = ChangeContent("/someurl, $("#resultContainer"));
function doFurtherStuff(responseText, statusText, XMLHttpRequest)
{
var identifier = '#' + this.id;
...
}
Notice that the doFurtherStuff must have the correct "this" object value which is the context specified in ChangeContent function. When I tried to use different deferred then() ...etc. functions in JQuery 1.8.1 to solve the above this.callback.call(this.context[0], data); problem after the upgrade the "this" object in the callback function had different value since I guess the new JQuery library handles that differently.
Is there anyway to fix the error above while limiting the change to ChangeContent function only as I try to avoid asking all users to change the way they call and handle call backs from that function?
When you add the context option, you are telling jQuery what this should be inside of the success callbacks. That means you can't access the options passed into the ajax request. Either don't supply a context, or pass in the callback manually.
function ChangeContent(url, somepageobject) {
var callback = doFurtherStuff;
var xhrobj = $.ajax({
url: url,
context: somepageobject,
success: function(data) {
somepageobject.html($(data));
callback.call(this[0], data, "ok"); // >> Code breaks here
}
});
return xhrobj;
}
Update:
If you want to instead continue using your code as-is, simply rename the context property.
function ChangeContent(url, somepageobject) {
var xhrobj = $.ajax({
url: url,
thecontext: somepageobject,
callback: doFurtherStuff,
success: function(data) {
somepageobject.html($(data));
this.callback.call(this.thecontext[0], data, "ok"); // >> Code breaks here
}
});
return xhrobj;
}
Hey. I need some help with jQuery Ajax calls. In javascript I have to generste ajax calls to the controller, which retrieves a value from the model. I am then checking the value that is returned and making further ajax calls if necessary, say if the value reaches a particular threshold I can stop the ajax calls.
This requires ajax calls that need to be processes one after the other. I tried using async:false, but it freezes up the browser and any jQuery changes i make at the frontend are not reflected. Is there any way around this??
Thanks in advance.
You should make the next ajax call after the first one has finished like this for example:
function getResult(value) {
$.ajax({
url: 'server/url',
data: { value: value },
success: function(data) {
getResult(data.newValue);
}
});
}
I used array of steps and callback function to continue executing where async started. Works perfect for me.
var tasks = [];
for(i=0;i<20;i++){
tasks.push(i); //can be replaced with list of steps, url and so on
}
var current = 0;
function doAjax(callback) {
//check to make sure there are more requests to make
if (current < tasks.length -1 ) {
var uploadURL ="http://localhost/someSequentialToDo";
//and
var myData = tasks[current];
current++;
//make the AJAX request with the given data
$.ajax({
type: 'GET',
url : uploadURL,
data: {index: current},
dataType : 'json',
success : function (serverResponse) {
doAjax(callback);
}
});
}
else
{
callback();
console.log("this is end");
}
}
function sth(){
var datum = Date();
doAjax( function(){
console.log(datum); //displays time when ajax started
console.log(Date()); //when ajax finished
});
}
console.log("start");
sth();
In the success callback function, just make another $.ajax request if necessary. (Setting async: false causes the browser to run the request as the same thread as everything else; that's why it freezes up.)
Use a callback function, there are two: success and error.
From the jQuery ajax page:
$.ajax({
url: "test.html",
context: document.body,
success: function(){
// Do processing, call function for next ajax
}
});
A (very) simplified example:
function doAjax() {
// get url and parameters
var myurl = /* somethingsomething */;
$.ajax({
url: myurl,
context: document.body,
success: function(data){
if(data < threshold) {
doAjax();
}
}
});
}
Try using $.when() (available since 1.5) you can have a single callback that triggers once all calls are made, its cleaner and much more elegant. It ends up looking something like this:
$.when($.ajax("/page1.php"), $.ajax("/page2.php")).done(function(a1, a2){
// a1 and a2 are arguments resolved for the page1 and page2 ajax requests, respectively
var jqXHR = a1[2]; /* arguments are [ "success", statusText, jqXHR ] */
alert( jqXHR.responseText )
});