Delay till ajax response like thread.sleep() - javascript

I have button which post values of form to url but during post i want to capture that value into my database too.
So on button click i made new thread of ajax and paused by while loop so user can not redirect due to post of form.
But problem is program not responding in while loop and not posting ajax call.
function btnSubmitId_Onclick() {
window.setTimeout(function () {
var FirstName = $(txtFirstNameId).val()
var Email = $(txtEmailId).val()
AJAXPost( //Url
"Signup"
, //Data
{Ip: Ip, CustomerKey: CustomerKey, FirstName: FirstName, Email: Email }
, //Success
function (data) {
response2 = true;
}
, //error
function (xhr, textStatus, errorThrown) { }
);
}, 0);
var date = new Date();
var curDate = null;
do { curDate = new Date(); }
while (response2 == false)
}
var response2 = false;

You really shouldn't do that. Active waiting is likely to block the whole browser or at least the current tab.
Put all code that needs to run after the request succeeded in the success callback.
Since you apparently want to both submit the form normally and use AJAX (why?!), the solution is rather simple: prevent the original submit from being handled by the browser by calling e.preventDefault() (e being the first argument passed to the jQuery event handler) and after the AJAX request succeeded .submit() the form. To avoid the AJAX request from being sent again you might need to unbind the submit event handler or set a variable after the AJAX request completed.

Related

Why do I get a Bad Request with this jQuery post?

I have this JavaScript that executes when the commit button for a form is clicked. It is supposed to submit the form body and a file:
$("#submitButton").off("click").on("click", function(evt) {
evt.preventDefault();
var url = "/portal/ProjectAuthority/Boq" + "?projectId=" + "0831260e-7018-dd49-9a84-daaf442bc1ec";
debugger;
var data = new FormData();
//Form data
var formData = $('#BoqReviewForm').serializeArray();
$.each(formData, function (key, input) {
data.append(input.name, input.value);
});
//File data
var fileData = $('input[name="boqFile"]')[0].files;
for (var i = 0; i < fileData.length; i++) {
data.append("boqFile", fileData[i]);
}
$("#boqDataWrapper").empty();
$.post({
url: url,
data: data,
processData: false,
contentType: false,
success: function (resp) {
setTimeout(function() {
getBoqReviewData(resp.importId);
},
100);
},
error: function(xmlHttpRequest, textStatus, errorThrown) {
alert(errorThrown);
}
});
return false;
});
The url is:
http://localhost/portal/ProjectAuthority/Boq?projectId=0831260e-7018-dd49-9a84-daaf442bc1ec
and the action method signature is:
public ActionResult Boq(Guid projectId, BoqUploadViewModel model, HttpPostedFileBase boqFile)
When I click the submit button, the jQuery Ajax error function is invoked before my breakpoint at the beginning of the action method, so the action method itself is not returning Bad Request, whatever tries to invoke the action method is.
Is there any obvious reason for the Bad Request error?
It turns out the viewmodel property for boqFile has a homemade data annotation attribute that is supposed to validate file extensions, e.g. to only xlsx, and that attribute was constantly failing, causing a bad request because the ajax call didn't return the model with errors.
I found this by skipping the ajax call and doing a straight postback, and then I got an error about the file extension, which was correct. I removed the faulty attribute, and the postback returned the valid json intended for the ajax call. Then I just went back to the ajax call and all is working.

submit form with ajax validation jquery / standard javascript

I'll start with an apology - I'm a .NET coder with little (no) front-end experience.
When the user clicks on Submit, the form needs to call a REST service, if the service returns true then the user is presented with a warning that a duplicate exists and are asked whether they want to continue. Appreciate any help.
I have the Submit button ONCLICK wired up to Approve()
When the checkForDuplicateInvoice() gets called, it passes the control back to the calling function right away before the ajax call has a chance to get the result. The effect is that the Validate() function finishes without taking into account whether or not a duplicate invoice exists.
I need help in modifying the form so that when the user clicks on the submit button, the form validates (including the ajax call to the db) before finally submitting.
I've modified the code based on Jasen's feedback.
I'm including https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js in my header.
The error I get now is "Object doesn't support property or method 'button'"
What I have now for my form submission/validation is:
$(document).ready(function () {
$("#process").button().click( function () {
if (ValidateFields()) { // internal validation
var companyCode = document.getElementById("_1_1_21_1").value;
var invoiceNo = document.getElementById("_1_1_25_1").value;
var vendorNo = document.getElementById("_1_1_24_1").value;
if (vendorNo == "undefined" || invoiceNo == "undefined" || companyCode == "undefined") {
return false;
}
$.ajax({ // external validation
type: "GET",
contentType: "application/json;charset=utf-8",
//context: $form,
async: false,
dataType: "jsonp",
crossDomain: true,
cache: true,
url: "http://cdmstage.domain.com/services/rest/restservice.svc/CheckDuplicateInvoice?InvoiceNumber=" + invoiceNo + "&VendorNumber=" + vendorNo + "&CompanyCode=" + companyCode,
success: function (data) {
var result = data;
var exists = result.CheckForInvoiceDuplicateResult.InvoiceExists;
var valid = false;
if (exists) {
if (confirm('Duplicate Invoice Found! Click OK to override or Cancel to return to the form.')) {
valid = true;
}
}
else {
valid = true; // no duplicate found - form is valid
}
if (valid) {
document.getElementById("_1_1_20_1").value = "Approve";
doFormSubmit(document.myForm);
}
},
error: function (xhr) {
alert(xhr.responseText);
}
});
}
});
});
First review How do I return the response from an asynchronous call? Understand why you can't return a value from the ajax callback functions.
Next, disassociate the submit button from the form to prevent it from performing default submission. Test it to see it does nothing.
<form>
...
<button type="button" id="process" />
</form>
Then wire it up to make your validation request
$("#process").on("click", function() {
if (valid()) {
$(this).prop("disabled", true); // disable the button to prevent extra user clicks
// make ajax server-side validation request
}
});
Then you can make your AJAX request truly asynchronous.
$.ajax({
async: true,
...,
success: function(result) {
if (exists) {
// return true; // returning a value is futile
// make ajax AddInvoice call
}
}
});
Pseudo-code for this process
if (client-side is valid) {
server-side validation: {
on response: if (server-side is valid) {
AddInvoice: {
on response: if (successful) {
form.submit()
}
}
}
}
}
In the callback for the server-side validation you make the AddInvoice request.
In the callback for AddInvoice you call your form.submit().
In this way you nest ajax calls and wait for each response. If any fail, make the appropriate UI prompt and re-enable the button. Otherwise, you don't automatically submit the form until both ajax calls succeed and you call submit() programmatically.

More than 1 ajax function being called at once, PHP, AJAX

I have a working ajax function that when called will display the current time, and then setTimeout for ten seconds before displaying the new time. I call this function when onkeyup is triggered on an text input, and it works. But there is a slight problem. If I type something else in the text input after the ajax function has already been called, it'll call another ajax function, and have two ajax functions running at the same time. For example:
If the first ajax function was called at 3:00:00 when it was triggered, and the second ajax function is called at 3:00:05, that means that there are now two ajax functions running at the same time. The first ajax function will be triggered again at 3:00:10, after the 10 second setTimeout, and the second ajax function will be triggered again at 3:00:15, after its 10 second setTimeout. So the more times you trigger the onkeyup in the text input, the more times the function will be called. I just want 1 function of itself to be running at the same time, not 2, 3, or more. How do I do that? Thanks.
ajax.php
<script type = "text/javascript">
function timeoutAjax(url,type,theName,id,timeout) {
$.ajax({
type: "POST",
url: url,
data: { select: $(type+'[name='+theName+']').val()},
error: function(xhr,status,error){alert(error);},
success:function(data) {
document.getElementById( id ).innerHTML = data;
setTimeout(function() { timeoutAjax(url,type,theName,id,timeout); }, timeout);
}
});
}
</script>
test1.php
<?php
include('ajax.php');
echo "<input type = 'text' name = 'name' onkeyup = 'timeoutAjax(\"test2.php\",\"input\",\"name\",\"output1\",\"10000\")'>";
echo "<div id = 'output1'/>";
?>
test2.php
<?php
$time = date('H:i:s A');
echo $time;
?>
************MORE DETAILS************
echo "<input type = 'submit' name = 'name1' value = 'Reset' onclick = 'timeoutAjax(\"test2.php\",\"input\",\"name1\",\"output1\",\"10000\")'>";
echo "<input type = 'submit' name = 'name2' value = 'Reset' onclick = 'timeoutAjax(\"test2.php\",\"input\",\"name2\",\"output2\",\"10000\")'>";
echo "<div id = 'output1'/>";
echo "<div id = 'output2'/>";
If I understand your question correctly, you actually trying to achieve two things here:
1. Only the last ajax call
After the last key stroke, do some ajax call. Any ajax call that is already busy can be skipped, you are just interested in the last one.
This should not be to hard. jQuery returns an xhr object when you call the ajax function. On that xhr object, you can just call the abort() method to cancel a pending call. (Abort Ajax requests using jQuery)
2. Repeat the ajax call every x time
Right now you set a timeout in your ajax success function that will just repeat the call after a given time. Problem is that when you call your ajax function again from the outside (so not recursively I mean, but by another keystroke or something) you will just create another infinite string of ajax calls. After a while you'll end up with a huge queue of calls that will start to overlap and eat up all your resources.
This can easily be solved by storing the result of that setTimeout in a variable, and calling clearTimeout on that variable each time before you set a new timeout. This way you cancel the old 'queue' and just start a new one.
So enough poor english, let's try to show what I mean by updating your code:
function timeoutAjax(url, type, theName, id, timeout, trigger) {
// abort pending calls
if (trigger.xhr) {
trigger.xhr.abort();
}
// abort queued calls
clearTimeout(trigger.queued);
// make the call
trigger.xhr = $.ajax({
type: "POST",
url: url,
data: {
select: $(type + '[name=' + theName + ']').val()
},
error: function (xhr, status, error) {
alert(error);
},
success: function (data) {
document.getElementById(id).innerHTML = data;
// queue a new call
trigger.queued = setTimeout(function () {
timeoutAjax(url, type, theName, id, timeout, trigger);
}, timeout);
}
});
}
Just one more sidenote. Even with the changes I made to your code, you will be aborting and making a new ajax call on every key stroke. And aborting an ajax call does not automatically mean your server stops handling the request, depnding on what backend you are using. For the simple php script you are using now it is probably fine, but still, it is probably better to wait until the user is done with typing before you make your first call. This is called Debouncing and isn't very hard to implement either: http://davidwalsh.name/javascript-debounce-function
Create a status variable that tracks if the ajax call is running. Set it to false initially. Then when the function is called, check the status; if not running execute the ajax call, set the status var to true, then set it to false again in the success callback:
<script type = "text/javascript">
//Create the status var (This may not be the best place to initialize it). Use your best judgement.
var running = false;
function timeoutAjax(url,type,theName,id,timeout) {
//Check if there is an ajax call in progress. If not execute one.
if(!running)
{
//Change the status to running
running = true;
console.log('In if')
console.log(running)
$.ajax({
type: "POST",
url: url,
data: { select: $(type+'[name='+theName+']').val()},
error: function(xhr,status,error){alert(error);},
success:function(data) {
document.getElementById( id ).innerHTML = data;
setTimeout(function() {
//Set the status to false for the inner function call
running = false;
timeoutAjax(url,type,theName,id,timeout);
//Set the status to true for the outer function call
runnng = true;
}, timeout);
}
});
}
}
</script>
The outer function which triggers the first ajax call and the timeout will only be run once,; however, the inner function will run every ten seconds continuously.
I hope this works for you, If so, please accept this answer. Thanks

ajax sends POST twice, receiving double/repetitive results from PHP

i found out my JS sends POST method twice to my PHP file, thats why i keep getting double/repetitive results from my PHP.
This JS event, upon .keyup() will execute an ajax.
$(document).ready(function() {
var getUrl = $('#url');
var youtube = regex here
var web = regex here
getUrl.keyup(function() {
if (youtube.test(getUrl.val())) {
var youtube_url = getUrl.val().match(youtube)[0];
$.ajax ({
type:"POST",
url:"getyoutube.php",
data: {youtube_url:youtube_url},
success: function(html) { $('.echotest').append(html); }
}); }
else if (web.test(getUrl.val())) {
var extracted_url = getUrl.val().match(web)[0];
$.post("curl_fetch.php?url="+ extracted_url, {
}, function(response){
$('#loader').html($(response).fadeIn('slow'));
$('#cur_image').val(1);
});}
});
});
the data will be received by getyoutube.php and should only print json result of a particular youtube video once.
//some code ommitted
$youtube ="https://gdata.youtube.com/feeds/api/videos/'.$matches[0].'?v=2&alt=jsonc";
$curl = curl_init($youtube);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$return = curl_exec($curl);
curl_close($curl);
$test = json_decode($return, true);
print_r($test);
i cant seem to figure out why my AJAX post keeps sending POSTS method twice
Couple of things to try:
1) Make sure you bind and unbind your key up event
2) Use a global variable to make sure only one ajax request gets sent at once
i.e.:
var ajaxrequest = false; //GLOBAL
function getyoutubedata(){
if(ajaxrequest != false){
return;
}
ajaxrequest = $.ajax ({
type:"POST",
url:"./includes/getyoutube.php",
data: {youtube_url:youtube_url},
success: function(html) { $('.echotest').append(html); ajaxrequest = false; }
});
}
Btw thing to note the youtube api supports jsonp callbacks so you might want to consider doing this through that
3) Try to check if the content of the input field has changed even before calling the above function
You should show us the code with the .keyup() event, probably that's the place of an error. The event handler could execute a wrapper function for the ajax, instead of the ajax directly. For example, if you the keyup event is triggered, try to check if the input content has changed. If so, run ajax, if not - do nothing.
coverted this
$.ajax ({
type:"POST",
url:"getyoutube.php",
data: {youtube_url:youtube_url},
success: function(html) { $('.echotest').append(html); }
}); }
to this.
$.post("./includes/getyoutube.php?url="+ youtube_url, {
}, function(response){
$('.echotest').append(response);
});
POST method is now being executed once. although i cant really explain technically why it worked.

setTimeout doesn't start until I stop the page

On the event of a form submit, I have a jquery ajax function that queries for the amount of data uploaded from a file that I can use in making a progress bar. This is my js file:
var submitted = '';
var counter = 0;
$('#webfileuploadform').submit(function(){
if(submitted == 'submitted') return false; // prevents multiple submits
var freq = 1000; // freqency of update in ms
var progress_url = '/upload_progress/' + $('#id_progress_id').val(); // ajax view serving progress info
update_progress_bar();
function update_progress_bar(){
$.ajax({
dataType:"json",
url: progress_url,
success: function(data){
counter ++
console.log('hit success ' + counter);
},
complete: function(jqXHR, status){
if (status == 'success'){
console.log('hit complete', status == success')
} else {
console.lot('hit complete', status == something else')
}
}
});
setTimeout(function(){update_progress_bar()}, freq);
}
submitted = 'submitted'; // marks form as submitted
});
So, the user will use the form to select the file then click submit. This all happens just fine. The form submits, the file is uploaded, and the progress shows just fine when I open my ajax view in a separate tab and keep refreshing it. What I don't understand is why the update_progress_bar function runs once until I stop the page. I'll upload a file but until I click the 'x' on my browser I won't get any of the 'hit success' in my console. After I hit stop, the console spits out the 'hit success ' plus the counter. But I shouldn't have to hit stop to do this. I need this to work when the file is uploading.
Any ideas what my problem is?
**
EDIT
**
Not sure if it makes a difference, but I am doing all this on a django development server. Which I think shouldn't have a problem with two XMLHTTPRequests in the same session.
Try this:
var $submitted = '';
$('#webfileuploadform').submit(function(){
if($submitted == 'submitted') return false; // prevents multiple submits
var freq = 1000; // freqency of update in ms
update_progress_bar();
function update_progress_bar(){
var progress_url = '/upload_progress/' + $('#id_progress_id').val(); // ajax view serving progress info
$.ajax({
dataType:"json",
url: progress_url,
success: function(data){
console.log("hit success");
},
complete:function(jqXHR, status) {
if (status == 'success') {
setTimeout(update_progress_bar, freq);
}
}
});
}
$submitted = 'submitted'; // marks form as submitted
});
As it stands, the code looks good to me. I would add some more console logging to make sure the ajax call is returning with the status you expect:
complete:function(jqXHR, status) {
console.log('got to complete, status: ', status);
if (status == 'success') {
console.log('status is success, calling setTimeout.');
setTimeout(update_progress_bar, freq);
}
}
In the ajax function I set the async setting to false:
$.ajax({
async: false,
...
});
This has solved the problem. I have no idea how. From what I understand, this setting forces the ajax request to wait until all other http requests are finished before allowing it to continue. With that being the case, I have no idea how this works. I'll keep from answering my own question in case someone knows why this is working this way...

Categories

Resources