function pdfToImgExec(file, IsfirstLogging, folder, round) {
alert(file);
var postString = file + '&' + IsfirstLogging + '&' + folder + '&' + round;
var errorMsg = (folder == 'Incoming' ? '<p>error in incoming folder</p>' : '<p>error in other folder</p>');
$.ajax({
type: "POST",
cache: false,
async: false,
url: "pdfToImgExec.php",
data: {
"data": postString
},
dataType: "html",
beforeSend: function () {
alert(file + 'a');
$('#pdfToImgResult').html('<p>Converting' + file + ', Please wait......</p>');
},
success: function (data) {
if(data == '1') {
$('#pdfToImgResult').html('<p>Complete convert ' + file + '</p>');
} else if(round < 4) {
$('#pdfToImgResult').html('<p>Fail to convert , retry ' + round + ' round <img src="loading.gif" height="20" width="20"/></p>');
round++;
pdfToImgExec(file, 'false', folder, round);
} else {
folder == 'Incoming' ? tempFailIncomingFiles.push(file) : tempFailResultFiles.push(file);
}
},
error: function (x, t, m) {
$('#pdfToImgResult').html(errorMsg);
alert(t);
releaseBtn();
}
});
}
The problem of this ajax call is I can alert the (file + 'a') in the beforeSend function , but the
$('#pdfToImgResult').html('<p>Converting' + file + ', Please wait......</p>');
is not working, it will not display anything but only jumped to the
$('#pdfToImgResult').html('<p>Complete convert ' + file + '</p>');
after the ajax call is finished.
Is it due to async:false? How to fix the problem ? thanks.
It's because you're using async: false,, so the function blocks until the request is complete, preventing a redraw until everything is done.
You seem to be all set up with callbacks, so there doesn't seem to be any reason to make a blocking xhr request. Just remove the async: false,, and you should be all set.
Here's a quick example of how to deal with asynchronous code. I've removed most of your code to keep it brief.
// --------------------------------new parameter-------------v
function pdfToImgExec(file, IsfirstLogging, folder, round, callback) {
// your code...
$.ajax({
type: "POST",
cache: false,
// async: false, // Remove this line!
url: "pdfToImgExec.php",
data: {
"data": postString
},
dataType: "html",
beforeSend: function () {
$('#pdfToImgResult').html('<p>Converting' + file + ', Please wait......</p>');
},
success: function (data) {
// your code...
// Invoke the callback, passing it the data if needed
callback(data)
},
error: function (x, t, m) {
// your code;
}
});
}
When you call pdftoImgExec, pass a function as the last parameter that will be invoked when the response is complete. That function is where your code resumes.
pdfToImgExec(..., ..., ..., ..., function(data) {
// resume your code here.
alert(data);
})
Related
I'm having trouble with my functions running before Ajax requests (the first to a local JSON, the second to an online resource) have finished.
In this example I want countTheMovies to run at the end after my application has got all the information it needs and populated the divs. Instead it's running straight away.
I tried to delay it using an if condition, but with no joy. I've also tried with callbacks, but think I must be getting those wrong (I'm assuming callbacks are the answer). I'm aware of timed delays, but because in the actual project I'm sourcing 250+ movies (and because a timed delay seems like cheating) I thought I'd ask here instead.
Can anyone recommend JavaScript or jQuery code to fix this problem?
$(function(){
getMovieList();
});
function getMovieList() {
$.ajax({
url: "movielist.json",
type: "GET",
dataType: "JSON",
success: function(data) {
for (var i = 0; i < data.length; i++) {
var title = data[i].title.toLowerCase().split(" ").join("+");
var year = data[i].year;
i === data.length - 1
? getMovieInfo(title, year, true)
: getMovieInfo(title, year, false);
}
}
});
}
function getMovieInfo(title, year, isLast) {
$.ajax({
url: "https://www.omdbapi.com/?t=" + title + "&y=" + year + "&plot=short&r=json",
type: "GET",
crossDomain: true,
dataType: "JSON",
success: function(val) {
if (!val.Error) {
movie = title.replace(/[^a-z0-9\s]/gi, '');
$("#app").append(
// appending info to divs
);
}
}
});
if (isLast) countTheMovies();
};
function countTheMovies() {
$("#app").append("There are " + $(".movie").length + " movies.");
}
A plunker of my failings: https://plnkr.co/edit/0mhAUtEsaOUWhkZMJqma?p=preview
You've almost got it!
The same way that you call getMovieInfo in the success callback of getMovieList, you should be calling countTheMovies in the success callback of getMovieInfo.
As Jacob said above, move the countTheMovies call inside the AJAX request.
$(function(){
getMovieList();
});
function getMovieList() {
$.ajax({
url: "movielist.json",
type: "GET",
dataType: "JSON",
success: function(data) {
for (var i = 0; i < data.length; i++) {
var title = data[i].title.toLowerCase().split(" ").join("+");
var year = data[i].year;
i === data.length - 1
? getMovieInfo(title, year, true)
: getMovieInfo(title, year, false);
}
}
});
}
function getMovieInfo(title, year, isLast) {
$.ajax({
url: "https://www.omdbapi.com/?t=" + title + "&y=" + year + "&plot=short&r=json",
type: "GET",
crossDomain: true,
dataType: "JSON",
success: function(val) {
if (!val.Error) {
movie = title.replace(/[^a-z0-9\s]/gi, '');
$("#app").append(
// appending info to divs
);
if (isLast) countTheMovies();
}
}
});
};
function countTheMovies() {
$("#app").append("There are " + $(".movie").length + " movies.");
}
Just put your countTheMovies() logic inside of the success callback of the AJAX request in getMovieInfo if you want it to run on success.
You can call your countTheMovies() function from inside the success field of your Ajax call. This way it will make the function call when you intend it to.
Try out this
$(function(){
getMovieList();
});
function getMovieList() {
$.when( $.ajax({
url: "movielist.json",
type: "GET",
dataType: "JSON",
success: function(data) {
for (var i = 0; i < data.length; i++) {
var title = data[i].title.toLowerCase().split(" ").join("+");
var year = data[i].year;
i === data.length - 1
? getMovieInfo(title, year, true)
: getMovieInfo(title, year, false);
}
}
}) ).then(function( data, textStatus, jqXHR ) {
countTheMovies();
});
}
function getMovieInfo(title, year, isLast) {
$.ajax({
url: "https://www.omdbapi.com/?t=" + title + "&y=" + year + "&plot=short&r=json",
type: "GET",
crossDomain: true,
dataType: "JSON",
success: function(val) {
if (!val.Error) {
movie = title.replace(/[^a-z0-9\s]/gi, '');
$("#app").append(
// appending info to divs
);
}
}
});
};
function countTheMovies() {
$("#app").append("There are " + $(".movie").length + " movies.");
}
I want to use jquery for checking sites servers one by one and if the server is ok start grabbing pages.
But in the following code, the loop execute at the first and 2 message appears at the first lines:
start analyzing site 1
start analyzing site 2
start grabbing site 1
start grabbing site 2
...
How I can change this to:
start analyzing site 1
start grabbing site 1
...
start analyzing site 2
start grabbing site 1
...
I am new in Jquery, but I have read about promise and deferrals but could not write the correct code.
I tested this code by async:false. It solves the problem, But I don't want to use this approach (You know the reason).
new_links_arr() = array('site1', 'site2');
function check_server(response) {
var new_links_c = new_links_arr.length;
for (var n = 0; n < new_links_c; n++) {
var this_link = new_links_arr[n];
if (this_link.length > 5) {
$("#responds").append("<hr/> start analyzing site: " + this_link + "");
var myData = 'mod=chk_srv&url=' + encodeURIComponent(this_link) + '&mk_rds_dir=1';
$.ajax({
type: "GET",
url: my_url,
dataType: "json",
data: myData,
cache: false,
success: grab_site,
error: end_error
});
}
}
}
function grab_site(response) {
$("#responds").append(" " + response.the_msg + " ");
var status = response.status;
if (status == 1) {
$("#responds").append(" start grabbing site ");
var myData = 'mod=chk_home&url=' + encodeURIComponent(response.url);
$("#Loding_info").html("Get Homapage and Detecting software from " + response.url);
$.ajax({
type: "POST",
url: my_url,
dataType: "json",
data: myData,
success: parse_jdata,
error: end_error
})
} else {
$("#responds").append("stop");
end_ajax();
}
}
You should start the next test after you finish processing the previous one.
var new_links_arr = ['site1', 'site2'];
var new_links_index = 0;
function check_server() {
if (new_links_index >= new_links_arr.length) {
return;
}
var this_link = new_links_arr[new_links_index];
if (this_link.length > 5) {
$("#responds").append("<hr/> start analyzing site: " + this_link + "");
var myData = {
mod: 'chk_srv',
url: this_link,
mk_rds_dir: 1
};
$.ajax({
type: "GET",
url: my_url,
dataType: "json",
data: myData,
cache: false,
success: grab_site,
error: end_error
});
}
}
function grab_site(response) {
$("#responds").append(" " + response.the_msg + " ");
var status = response.status;
if (status == 1) {
$("#responds").append(" start grabbing site ");
var myData = {
mod: 'chk_home',
url: response.url
};
$("#Loding_info").html("Get Homepage and Detecting software from " + response.url);
$.ajax({
type: "POST",
url: my_url,
dataType: "json",
data: myData,
success: parse_jdata,
error: end_error
})
} else {
$("#responds").append("stop");
end_ajax();
}
}
function parse_jdata(response) {
// do your processing
// ...
new_links_index++;
check_server();
}
My code was long (more than 10 functions). So I cut some piece of it and made a new array (The real array is made by php from previous response and post by json). This is the reason of mistakes in the code.
The idea by Barmar (incrementing the array index in the final function) was helpful. I changed my code and it is working nice now. Thank you for your help.
I added the new function for sending sites one by one to the next functions:
function walk_in_links_arr(new_links_arr2)
{
if (new_links_index >= new_links_arr2.length)
{
//alert(' new_links_index11 = ' + new_links_index);
$("#responds").append("all sites checking done. ");
pass_response_final();
}
var this_link = new_links_arr2[new_links_index];
//alert(' new_links_index22 = ' + new_links_index);
//alert (this_link);
if(this_link.length>5)
{
$("#responds").append(" start checking " + this_link + " ");
var myData = 'mod=chk_srv&url='+ encodeURIComponent(this_link)+'&mk_rds_dir=1';
$.ajax({
type: "GET",
url: my_url,
dataType:"json",
data:myData,
cache: false,
success:grab_site,
error:end_error
});
}
else
{
new_links_index++;
walk_in_links_arr(new_links_arr);
}
}
I'm trying to display two progress bars for multiple ajax requests. One progress bar reaches 100% each time one of my 18 ajax requests is complete and another reaches 100% when all 18 requests are complete. The first bar works great and is implemented in my ajax success callback. I'm having trouble triggering my second bar because it seems I need a second success callback...
Here is the code for my first ajax requests. It gets called 18 times because that is how many items are in my Config object.
for (var propt in Config) {
var db = '...';
var user = '...';
var pword = '...';
var func = '...';
var dat = {"...": propt };
var url = "https://...";
var callData = jQuery.extend({"Db": db, "User": user, "Password": pword, "Function": func}, dat);
$.ajax({
type: "POST",
url: url,
contentType: "application/json; charset=utf-8",
data: JSON.stringify(callData),
xhr: function() {
var xhr = new window.XMLHttpRequest();
//Download progress
xhr.addEventListener("progress", function(event){
var percentComplete = (event.loaded / event.total)*100;
//Do something with download progress
tableProgressBar(percentComplete);
}, false);
return xhr;
},
success: successHandlerRunTest1,
error: errorHandlerRunTest1,
dataType: "json"
});
$('#jsonMsg1').html('Running...');
$('#jsonRslt1').html(' ');
}
I would also like to fire this success function simultaneously.
success : function (serverResponse) {
response[response.length] = serverResponse;
$('#progress-bar').text(current + ' of ' + total + ' tables are done');
current++;
},
Unfortunately I don't believe I can call the second success function from within the first success function because the first receives special parameters containing JSON data.
I've tried something like...
success : function (serverResponse) {
response[response.length] = serverResponse;
$('#progress-bar').text(current + ' of ' + total + ' tables are done');
current++;
successHandlerRunTest1(data);
},
...but this doesn't work because the "data" object that my successHandlerRunTest1(data) receives is empty.
Is there a way to perform two success callbacks per ajax request?
Don't use the success parameter.
Use the done method to attach callbacks, as it returns the promise for chaining you can call it multiple times:
$.ajax({
type: "POST",
url: url,
contentType: "application/json; charset=utf-8",
data: JSON.stringify(callData),
xhr: function() {
var xhr = new window.XMLHttpRequest();
xhr.addEventListener("progress", function(event){
var percentComplete = (event.loaded / event.total)*100;
tableProgressBar(percentComplete);
}, false);
return xhr;
},
dataType: "json"
})
.done(successHandlerRunTest1)
.fail(errorHandlerRunTest1)
.done(function (serverResponse) {
response[response.length] = serverResponse;
$('#progress-bar').text(current + ' of ' + total + ' tables are done');
current++;
});
You could simply pass both callbacks inside the original success callback. Then use .apply to pass the same arguments as the success callback was originally called with.
success: function()
{
callbackOne.apply(this, arguments);
callbackTwo.apply(this, arguments);
}
see .apply() method.
see arguments property.
Also as a side note never ever put database usernames and passwords in javascript. Since anybody can access it.
Try (this pattern) , utilizing deferred.always()
html
<progress id="p1" max="1" value="0"></progress>
<progress id="p2" max="17" value="0"></progress>
<span id="jsonMsg1"></span>
<span id="progress-bar"></span>
js
$(function () {
var count = null;
var Config = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17];
for (var propt in Config) {
var db = '...';
var user = '...';
var pword = '...';
var func = '...';
var dat = {
"...": propt
};
var url = "/echo/json/";
var callData = jQuery.extend({
"Db": db,
"User": user,
"Password": pword,
"Function": func
}, dat);
var successHandlerRunTest1 = function (data, textStatus, jqxhr) {
// Do something with download progress
$("#p1").val(1);
};
var response = [];
$.ajax({
type: "POST",
url: url,
contentType: "application/json; charset=utf-8",
data: {
json: JSON.stringify(callData)
},
beforeSend: function (jqxhr, setiings) {
jqxhr.count = ++count;
// Do something with download progress
$("#p1").val(0);
},
/*
xhr: function() {
var xhr = new window.XMLHttpRequest();
//Download progress
xhr.addEventListener("progress", function(event){
var percentComplete = (event.loaded / event.total)*100;
//Do something with download progress
tableProgressBar(percentComplete);
}, false);
return xhr;
},
*/
success: successHandlerRunTest1,
error: function (jqxhr, textStatus, errorThrown) {
console.log(errorThrown)
},
dataType: "json"
})
.always(function (data, textStatus, jqxhr) {
$('#jsonMsg1').html('Running...');
response[response.length] = data;
$("#progress-bar")
.text(Number(data["..."])
+ ' of '
+ Config.length + ' tables are done');
$("#p2").val(Number(data["..."]));
// Do something with download progress
if (data["..."] === "17" && jqxhr.count === 18) {
console.log(data["..."]);
$('#jsonMsg1').html('Done...');
$("#progress-bar")
.text(Number(data["..."]) + 1
+ ' of '
+ Config.length + ' tables are done');
};
});
// $('#jsonRslt1').html(' ');
};
});
jsfiddle http://jsfiddle.net/guest271314/z6DzF/4/
See
http://api.jquery.com/jQuery.ajax/#jqXHR
http://api.jquery.com/deferred.always/
i have made a wrapper function for $.ajax, i pass url,type,data and success function name as argument to it when i need ajax request
function postdata(url, type, data, succ)
{
console.log(succ);
//alert(succ);
$.ajax({
url: url,
type: type,
dataType: "json",
data: data,
success: succ
});
return false;
}
now 4rth argument is success function's name but behaving differently, one time it is working with name+parenthesis only, not working without parenthesis example
del = function(data) {
alert("executed");
$(":checked").each(function() {
$(this).parent("li").slideUp();
});
$('#myModal').modal('hide');
};
postdata("delete/", "POST",gl_obj,del());
and other time it is working only name without parenthesis, example
temp = function(obj) {
obj = eval("(" + obj + ")");
document.getElementById('temp').innerHTML += "<ul>";
for (i in obj)
{
//document.write(obj[i].name+"<br/>");
document.getElementById('temp').innerHTML += "<li data-id='" + obj[i].id + "' class='mylist'><input type='checkbox' class='checkbx'>" + obj[i].name + "<span class='glyphicon glyphicon-remove to-close'></span></li>";
}
document.getElementById('temp').innerHTML += "</ul>";
};
postdata("get_names/", 'GET', "", temp);
so "die" doesnt works , "diw()" woks and executes the die function, in contrast to it "temp" works fine withour parenthesis, can any one clear this confusion why it is behaving differently? and whats the concept
This is really rather obvious when you look at what the parenthesis does.
functionname is a function, just sitting there doing nothing
functionname() means execute the function
You have written a function that passes along a function as a parameter (a callback). That callback function is then passed to ajax for it to call-back, when required.
You should never execute the callback when you call your method (e.g. del()).
You should always just pass the function (e.g. del). The ajax method will actually call the function you passed when it has completed.
Other problems
I gather the following is the code that will not "work":
del = function(data) {
alert("executed");
$(":checked").each(function() {
$(this).parent("li").slideUp();
});
$('#myModal').modal('hide');
};
postdata("delete/", "POST", gl_obj, del);
Written as shown above, it will "work", but only if the Ajax call succeeds. You might want to add the following for testing purposes:
function postdata(url, type, data, succ, err)
{
console.log(succ);
//alert(succ);
$.ajax({
url: url,
type: type,
dataType: "json",
data: data,
success: succ,
error: err
});
return false;
}
del = function(data) {
alert("executed");
$(":checked").each(function() {
$(this).parent("li").slideUp();
});
$('#myModal').modal('hide');
};
postdata("delete/", "POST", gl_obj, del, function(){alert('Oh crap!');});
Update (again):
Based on the comments and trials of the above code, the delete/ POST call to the server is failing.
Note: you do not need to return anything from your postdata method.
To see the error, change your code to:
function postdata(url, type, data, succ)
{
console.log(succ);
//alert(succ);
$.ajax({
url: url,
type: type,
dataType: "json",
data: data,
success: succ,
error: function( jqXHR, textStatus, errorThrown ){
alert(textStatus + " - " + errorThrown);
}
});
}
postdata("delete/", "POST", gl_obj, del);
the actual problem was of dataType being passed wrong for del callbackfuncion se i modified the potion of code
function postdata(url, type, data, succ,dataType)
{
console.log(succ);
//alert(succ);
$.ajax({
url: url,
type: type,
dataType: dataType,
data: data,
success: succ
});
return false;
}
Now this will be based as blank in case of del and json in case of temp
for del:
postdata("delete/", "POST",gl_obj,del,"");
and for temp
postdata("get_names/", 'GET', "", temp,"json");
Getting problems in Response.d , based on the result which is returning by the checkusers() function I am saving the values. If the entered name is in already in database it should say "User already exists", if it is not in database it should create a new record.
But I am not getting the correct value from (response), I observed that Console.log(response.d) giving me correct values like 'true' or 'false'. I tried everything I know like-
changing async:"false"
var jqXHR = $.ajax({ and returning jqXHR.responseText
But none of they worked for me . Please help me with this.
submitHandler: function (form) {
var txtName = $("#txtName").val();
var txtEmail = $("#txtEmail").val();
var txtSurName = $("#txtSurName").val();
var txtMobile = $("#txtMobile").val();
var txtAddress = $("#txtAddress").val();
var obj = CheckUser();
if (obj == false) {
$.ajax({
type: "POST",
url: location.pathname + "/saveData",
data: "{Name:'" + txtName + "',SurName:'" + txtSurName + "',Email:'" + txtEmail + "',Mobile:'" + txtMobile + "',Address:'" + txtAddress + "'}",
contentType: "application/json; charset=utf-8",
datatype: "jsondata",
async: "true",
success: function (response) {
$(".errMsg ul").remove();
var myObject = eval('(' + response.d + ')');
if (myObject > 0) {
bindData();
$(".errMsg").append("<ul><li>Data saved successfully</li></ul>");
}
else {
$(".errMsg").append("<ul><li>Opppps something went wrong.</li></ul>");
}
$(".errMsg").show("slow");
clear();
},
error: function (response) {
alert(response.status + ' ' + response.statusText);
}
});
}
else {
$(".errMsg").append("<ul><li>User Already Exists </li></ul>");
$(".errMsg").show("slow");
}
}
});
$("#btnSave").click(function () {
$("#form1").submit()
});
});
checkusers function is:
function CheckUser() {
var EmpName = $("#txtName").val();
$.ajax({
type: "POST",
url: location.pathname + "/UserExist",
data: "{Name:'" + EmpName + "'}",
contentType: "application/json; charset=utf-8",
datatype: "jsondata",
async: "true",
success: function (response) {
console.log(response.d);
},
error: function (response) {
alert(response.status + ' ' + response.statusText);
}
});
}
Just because your database returns true or false doesn't mean this also gets returned by your CheckUser().
There are several options here:
Either you make a local variable in your CheckUser, Make your Ajax call synchronous, set the local variable to response.d in the success function and then return that local variable.
Another option is to work with Deferred objects and make your submithandler Ajax call wait for the Checkuser Ajax call to return;
A third option is to call your create ajax call from your success callback in your CheckUser Ajax call if the user isn't created yet.
I would recommend either option 2 or 3, because option 1 is not userfriendly.