I am using below code
var lockonscreens = 1;
jQuery(document).ready(function(e) {
var noOfSelection = 0;
if(lockonscreens == 0){
// some stuff
}
if(lockonscreens == 1){
// some stuff
}
});
function ajaxcall(){
jQuery.ajax({
url:
type:
data:
async: false,
success: function(data){
lockonscreens = data;
}
});
}
jQuery("#").click(function(){
ajaxcall();
});
I am using above code to get some data through ajax and set it to variable and depending on that variable a click event code may happen.
But on ajax call the global variable value doesn't get changed.
It remains the same even if the data changes in ajax.
Can anyone let me know what is the issue and how to correct it?
Remember that ajax is asynchronous, so if you call ajaxCall() and next an other function, ajax start the call to server and the function end.
When the server respond, the code after success: is executed.
Make sure you call the function in the success: function
Related
I have a function that goes to a PHP script which returns the Server Operating System.
The script is literally dead simple:
<?php
echo (strpos(PHP_OS, 'Linux') > -1 ? 'Lin' : 'Win');
My goal is to be able to differentiate between operating systems so that I can declare a global path variable in my .js file for future uses.
This is what I've done so far:
function serverOS()
{
var os;
$.ajax({
url: '../scripts/ajax/detect-os.php',
type: 'get',
success: function(res)
{
os = res;
return os;
},
error: function(res) {alert('Major Error!'); console.log(res)}
});
return os;
}
console.log(serverOS());
The ending console.log outputs undefined - but if I console.log os inside of the success callback function, then it outputs what I expect.
According to this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
I should be able to do what I want with the above script but it doesn't seem to work. How do I go about setting and getting a global variable using ajax in JavaScript/jQuery?
AJAX operations are asynchronous. They will not block the rest of your JavaScript from executing.
The final return statement in your function attempts to return os immediately (before the AJAX operation has completed. Remove that return statement and in the success handler take care of all the logic to get the value back to the caller.
function serverOS() {
// The AJAX method will invoke the logging function no matter what.
// But, it won't happen until the AJAX call is complete.
$.ajax({
url: '../scripts/ajax/detect-os.php',
type: 'get',
success: function(res) {
returnValue(res);
},
error: function(res) {
alert('Major Error!');
returnValue(res);
}
});
}
function returnValue(val){
console.log(val);
}
serverOS();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Scott's Answer definitely works - but there does also seem to be an alternative I stumbled across. There's an AJAX property called async. Setting this to false in my function means it becomes a synchronous ajax call. Changing my function to this:
var os;
function serverOS()
{
$.ajax({
url: '../scripts/ajax/detect-os.php',
type: 'get',
async: false,
success: function(res)
{
returnValue(res)
},
error: function(res)
{
alert('Major Error!');
returnValue(res)
}
});
}
function returnValue(val)
{
os = val;
return os;
}
serverOS();
console.log(os); //this print Lin on my Linux machine.
ref: https://api.jquery.com/jQuery.ajax/
Why is it that whenever I put an ajax inside a for loop, it doesn't synchronize well?
like for example, my code is:
function addToUserGroupList() {
_root.qDomId('js-assignGroupArrBtn').disabled = true
for (var i = 0; i < selectedIds.length; i++) {
$.ajax({
type: "POST",
url: 'groupManage.ashx',
dataType: 'text',
data: 'type=getInfo&groupId=' + selectedIds[i],
success: function (result) {
if (result != '') {
this.groupName = result.split('&')[0];
this.groupNotes = result.split('&')[2];
userGroupList.push({ 'uid': parseInt(selectedIds[i]),
'name': this.groupName,
'adminStr': this.groupNotes
});
_root.userListObj.gourpInst.gourpTB(userGroupList);
}
},
error: function (XMLHttpRequest, status, errorThrown) {
alert('failed to add to user\'s group.');
}
});
}
_root.qDomId('js-assignGroupArrBtn').disabled = false;
selectedIds = [];
}
Why is that it calls out selectedIds = []; first before the Ajax Query?
Is it possible to let the ajax queries be finished before proceding to selectedIds = [];? Because it clears the array right before it's finished doing the stuffs. :/
First off, you really need to understand how an Ajax call is Asynchronous (that's what the "A" in Ajax stands for). That means that calling $.ajax() only starts the ajax call (it sends the request to the server) and the rest of your code happily continues running. Sometimes LATER after the rest of your code has executed, the success or error callback handler is called when the response comes back from the server. This is NOT sequential programming and must be approached differently.
The #1 thing this means is that ANYTHING that you want to have happen after the ajax call MUST be in the success or error handler or called from there. Code located right after the ajax call will be run long before the ajax call completes.
So, there are different ways to structure your code to work with this asynchronous concept. If you only want one asynchronous ajax call in flight at a time, you have to do this restructuring and can't use a simple for loop. Instead, you can create an index variable and in the completion function, increment the index and kick off the next iteration. Here's one way to code it:
function addToUserGroupList() {
_root.qDomId('js-assignGroupArrBtn').disabled = true
var i = 0;
function next() {
if (i < selectIds.length) {
$.ajax({
type: "POST",
url: 'groupManage.ashx',
dataType: 'text',
data: 'type=getInfo&groupId=' + selectedIds[i],
success: function (result) {
i++;
if (result != '') {
this.groupName = result.split('&')[0];
this.groupNotes = result.split('&')[2];
userGroupList.push({ 'uid': parseInt(selectedIds[i]),
'name': this.groupName,
'adminStr': this.groupNotes
});
_root.userListObj.gourpInst.gourpTB(userGroupList);
}
next();
},
error: function (XMLHttpRequest, status, errorThrown) {
alert('failed to add to user\'s group.');
}
});
} else {
// last one done
_root.qDomId('js-assignGroupArrBtn').disabled = false;
selectedIds = [];
}
}
// kick off the first one
next();
}
I have the following javascript code:
function initSite(){
var site;
$.getJSON(www+'init/initSite', function(data) { site = data; });
}
$(document).ready(function(){
var site = initSite();
console.log(site);
}
which returns undefined... how can i store the json object that i recieve in the site variable so i can use it later?
EDIT:
This seem to work but im not sure if its correct to use this solution
var site = null;
$.ajax({
url: www+"init/initSite",
async: false,
dataType: 'json',
success: function (data) {
site = data;
}
});
console.log(site);
of course you got undefined because your function doesn't return anything and the ajax call is also asynchronous, so you have to wait the server response. Since $.ajax (and shortcuts) returns a promise you can do this task using deferred
function initSite(){
return $.getJSON(www+'init/initSite');
}
$(document).ready(function(){
$.when(initSite()).done(function(data) {
/* continue here the code execution, e.g. call another function */
doAllTheRemainingWorkWith(data)
});
}
as you can see this code is short and easy to read
function initSite(onSuccess){
$.getJSON(www+'init/initSite', onSuccess);
}
$(document).ready(function(){
initSite(function(data){
var site = data;
// initialize your code.
});
}
The problem is just a miss concept:
getJSON is an async call, and the site = data; will only happen way after the DOM is ready.
in order for you to make everything work the way it should, your initialization needs to start from your async call result and never before, for example:
// no need to wait for DOM ready to call `initSite`
initSite();
function initSite() {
$.getJSON(www+'init/initSite', function(data) {
initialization(data);
});
}
function initialization(site) {
// initialize all the things that need to be done
console.log(site);
}
$(document).ready(function(){
// do other stuff, for example show a loading message/image
}
I have a javascript function which supposed to check whether a task is completed.
When the task is completed there is a completion record in a file on the server.
The function supposed to make recursive calls to the server with some delay (potentially increasing) till it gets the completion record in the file.
The code given below makes excessive calls to the server with interval less than a second
example from Web Console:
[20:06:21.202] [20:06:21.563] [20:06:21.990]
But the task becomes competed on variable waittime value getting equal to max_waittime .
Though for a test case overall output is as expected, something is wrong with the function.
Where I'm wrong?
function check_status(time,div_id,filename) {
var status =0;
var waittime=time;
var max_waittime=11000000;
if (waittime < max_waittime){waittime=waittime+1000000; }
$.ajax({
type: "GET",
async: false,
url: "code_on_server_checking_file.php",
data: "f="+filename,
dataType: "text",
success: function(content) {
if (content ) {
// stuff related to output of the result
....
return status=1;
}
else {return status=0;}
}
});
if (status == 0 && waittime < 20000000){
setTimeout(check_status(waittime,div_id,filename),waittime);
}
else {alert('check_status passed!'+status+'|'+waittime);}
}
You need to pass check_status to setTimeout, not the value returned by invoking check_status(...). Since you need to pass parameters to check_status, use an anonymous function:
setTimeout(function () {
check_status(waittime, div_id, filename);
}, waittime);
You are calling the function instead of giving it as a reference to setTimeout. Wrap your function call in an anonymous function. Also, it would be better to simply set up the call in the ajax callback if needed rather than using a synchronous call. A synchronous call will tie up your browser.
function check_status(time,div_id,filename) {
$.ajax({
type: "GET",
url: "code_on_server_checking_file.php",
data: "f="+filename,
dataType: "text",
success: function(content) {
if (content ) {
// stuff related to output of the result
}
else {
time += 1000000;
if (time < 20000000) {
setTimeout( function() { check_status( time, div_id, filename); }, time );
}
}
}
});
}
"recursive calls to the server"? No, I don't think you want that.
If you go three deep, var max_waittime=11000000; will be created and initialized three times.
Maybe you can set the timeout value for the ajax call (ajax settings)
http://api.jquery.com/jQuery.ajax/
First of all, it looks like you don't understand that the ajax call is an asychronous call. Calling it just starts the networking operation and then the rest of your code continues executing. Some time later when the networking operation completes, your success function is called.
The ONLY place you can operate on the results of the ajax call is in the success function. You can't return a value from the success function and expect that to go anywhere. The only place that goes is somewhere inside the ajax code where it's dropped. If you need to do something with the results of the ajax call, then you need to either do that operation right in the success function or call some other function from the success function and pass it the returned data.
These are the parts of your code that do not work:
There's no point in returning the status value from the success function. It doesn't go anywhere except into the ajax function where the return value is just dropped.
This line of code if (status == 0 && waittime < 20000000){ is not doing what you want. Because the ajax call is asynchronous, the value of status has not yet been set by the ajax call when this line of code runs. Thus, it's ALWAYS 0 so your logic never works. You need to move this logic inside the success handler.
As others have said, your parameters to setTimeout are not right. You have to pass a function to setTimeout, not the results of executing a function.
This is the code I would suggest:
function check_status(time, div_id, filename) {
var max_waittime=11000000;
if (time < max_waittime){
time=time+1000000;
}
$.ajax({
type: "GET",
async: false,
url: "code_on_server_checking_file.php",
data: "f="+filename,
dataType: "text",
success: function(content) {
if (content ) {
// stuff related to output of the result
if (time < 20000000){
setTimeout(function() {check_status(time, div_id, filename)}, time);
}
}
}
});
}
Note that all handling of the ajax result is done in the success function and we pass an anonymous function to setTimeout that re-calls check_status after a time delay. This is not actually recursion (as others mentioned) because setTimeout allows check_status to return before it's called again some time later.
I have this function that makes an ajax call. I'm describing the problem in the last chunk of code comments.
function doop(){
var that = this;
var theold = "theold";
var thenew = "thenew";
$.ajax({
url: 'doop.php',
type: 'POST',
data: 'before=' + theold + '&after=' + thenew,
success: function(resp) {
if(resp == 1) {
$(that).siblings('.theold').html(thenew);
}
}
});
// I have some code here (out of the ajax) that **further** changes
// the .theold's html beyond what it was changed inside ajax success
// but the change depends on whether the resp (inside the success
// function) returned 1 or not, so this code out here depends on the ajax
// so it looks like I have to turn this ajax call into a sync ajax
return false;
}
Based on the problem as described in the code comments, what changes are best for this situation?
You need to set async: false for synchronous requests like this:
function doop(){
var that = this;
var theold = $(this).siblings('.theold').html();
var thenew = $(this).siblings('.thenew').val();
$.ajax({
async: false,
url: 'doop.php',
type: 'POST',
data: 'before=' + theold + '&after=' + thenew,
success: function(resp) {
if(resp == 1) {
$(that).siblings('.theold').html(thenew);
}
}
});
// some other code
return false;
}
see here for details
Either set the Ajax call to synchronous as stefita pointed out, or just move your code into the success callback. Why can't you do this? Even if it's another Ajax call it still can be done - you can nest them. With the information given by you so far (I can't see the problematic code, nor I have enough domain knowledge about your project) I don't see a problem, really.
I prefer to use callback to do the job because it achieves exactly the same result without actually making it synchronous. I use success:callback and then pass in the callback as a parameter.
function getData(callback) {
$.ajax({
url: 'register/getData',
data: "",
dataType: 'json',
success: callback
});
}
I then call this function like this:
getData(function(data){
console.log(data); //do something
});