i have a recursive Ajax call that work properly (PhP script called do his job, recursion is working, everything is fine) EXCEPT that in between the ajax calls i try to update a input text value to show the progress and it only updates once the whole loop is done.
Why is the line
$('#start_'+code_regional).val(msg);
not executing ?
function addLeads(code_regional, phone_numbers_start)
{
var databases = [];
var file = document.getElementById('file_'+code_regional).files[0];
var formData = new FormData();
formData.append('selectedDatabases', JSON.stringify(databases));
formData.append('code_regional', code_regional);
formData.append('phone_numbers_start', phone_numbers_start);
formData.append('phone_numbers_end', $('#end_'+code_regional).val());
formData.append('filePath', file);
$.ajax({
type: 'POST',
url: 'execute.php',
data: formData,
processData: false,
contentType: false,
success: function(msg){
$('#start_'+code_regional).val(msg);
if(msg < $('#end_'+code_regional).val())
{
addLeads(code_regional, msg);
}
else
{
$('#start_'+code_regional).val($('#end_'+code_regional).val());
}
}
});
}
If msg is an integer, you should compare integers instead of strings:
if( parseInt(msg,10) < parseInt($('#end_'+code_regional).val(),10) )
If it's still failing, try to add a console.log(...) before and after the test to know what's going on.
What do you mean in between the ajax calls? The code tells me, "if msg is less than y, call addLeads again, otherwise update the start field". So that's not tracking progress, the start field is only updated at the end. If you want to always update, move the update line outside the conditional.
Related
I have a timing problem with an ASP.NET core 5 system I'm working on. My page shows a DataTable with id='outsideDataTable', and when an item is selected a modal bootstrap dialog is shown. The submit button invokes method submitModal() which does this:
$.ajax({
type: 'POST',
url: '/api/Submit',
dataType: 'json',
statusCode: {
200: SubmitDone()
},
error: 'SubmitError',
data: $('#ModalForm').serialize()
});
The /api/Submit function calls the server's Submit function which does an update to the database. None of the C# code uses async coding. The database interface is NPoco. At the end of the update the function calls Ok() which I believe returns the status 200 to the ajax call.
[HttpPost("api/[action]")]
public IActionResult Submit(
int recordId,
... other formdata ...)
{
if (recordId == 0)
{
var sr = new Record() { ... fill with form data ... };
db.Insert(sr);
}
else
{
var sr = db.Single("select * from Records where recordId=#0", recordId);
if (sr == null)
return BadRequest($"Couldn't find record with ID={recordId}");
... update sr with form data ...
db.Update(sr);
}
return Ok();
}
The OK() function returns status of 200 back to the client, which should now execute the js SubmitDone() function.
function SubmitDone() {
$('#ModalDlg').modal('hide');
$('#outsideDataTable').DataTable().draw();
}
The problem is that when the outsideDataTable is redrawn from within the SubmitDone function, it will retrieve the data, which does not yet include the changes put into the database by the submit action routine. Why is that? In my opinion the database should have done its thing by the time the status 200 is returned to the ajax call, ergo when the redraw happens the database should have the new data.
As a matter of fact, in fiddler I see that the list load from the redraw happens before the ajax to the submit function.
I have not isolated this into working code I can share, but can do so if needed - unless someone knows what I'm doing wrong.
When you assign the SubmitDone function to the statusCode.200 callback you shouldn't use parentheses because this is making the function execute immediately. Instead, it should be like this:
$.ajax({
type: 'POST',
url: '/api/Submit',
dataType: 'json',
statusCode: {
200: SubmitDone
},
error: 'SubmitError',
data: $('#ModalForm').serialize()
});
I am sending Ajax request to php page using Javascript.
My main goals is to send ajax request to PHP page and get the response which I have done that already.
The problem is when the Ajax send back the response the Javascript cannot send this to HTML properly.
Look at my code so you can understand clearly.
Javascript code:
function get_rental_fee(){
var count_model = $('#count_model').val();
for(var i =0; i < count_model; i++){
var hours = $('#hours').val();
var modelid = $('#modelid_multi'+i).val();
var get_tax = $('#get_tax_multi'+i).val();
var get_counter = $('#get_counter_multi'+i).val();
var myData = "hours="+hours+"&modelid="+modelid+"&get_tax="+get_tax;
jQuery.ajax({
type: "POST", // Post / Get method
url: "get_rental_fee.php", //Where form data is sent on submission
dataType:"text", // Data type, HTML, json etc.
data:myData, //Form variables
success:function(response){
var result = response.split('|');
document.getElementById('rental_price_multi'+i).value=result[0];
document.getElementById('tax_multi'+i).value=result[1];
},
error:function (xhr, ajaxOptions, thrownError){
//On error, we alert user
alert(thrownError);
}
});
}
}
The problem is here:
document.getElementById('rental_price_multi'+i).value=result[0];
document.getElementById('tax_multi'+i).value=result[1];
The loop runs 3 times and Php is sending me back the response 3 times. But in Javascript Theses 2 lines are only showing VALUES of 3rd Times not 1st and 2nd.
But I am receiving response of all 3 times.
Also when I run the code the javascript returns back an error:
Uncaught Type Error: Cannot set Property 'value' of null
Please help me where I am doing wrong
Problem is $.ajax is by default async: true, so the value of i in loop is not the desired value when it reaches success.
You can simply make the ajax sync:
$.ajax({
async: false,
...
})
Edited:
If you still want to it to be async, you need to use closures.
for(var i =0; i < count_model; i++){
(function(i){// closure `i`
$.ajax({
type: "POST",
...
});
})(i);//<-- for loop `i`
}
Your problem is that i inside the callback no longer has the value it did when you registered the callback. This is a very common problem.
A common solution is to "close over" the variable i so that it retains the correct value:
success: (function(i) {
return function(response) {
var result = response.split('|');
document.getElementById('rental_price_multi'+i).value=result[0];
document.getElementById('tax_multi'+i).value=result[1];
})(i)
The outer function is passed i as a parameter, at which point its value in the inner callback function becomes fixed.
I have simple autocomplete input field with Javascript like this:
$('#search').on('keyup', function () {
var query = $(this).val();
$.ajax({
type: "GET",
url: "/search",
data: { query: query }
}).done(function (results) {
showSearchResults(results);
});
});
Sometimes first call takes more time then second or third and results are overridden.
How can I make sure that results only from the latest successful call are displayed?
I mean if I got response from call #3 - I no longer care about calls #1 and #2 and don't want them to override results of call #3.
Ajax function is in default asynchronous it means that many of functions can run on same time. If You wrote 3 letters it will run 3 times, after 3 keyups. If you want to run function in sequence just add setting async: false.
$.ajax({
type: "GET",
url: "/search",
async: false,
data: { query: query }
}).done(function (results) {
showSearchResults(results);
});
But i think You should add some delay, so function will not run immediately after every keyup, just after last one.
I suggest that you bind an incremental id to each ajax request that you send. When you get a response, just check that it carries last given id.
let lastXHRid=0; // tracker of last sent ajax request
$('#search').on('keyup', function () {
let reqXHR = $.ajax({ // create a variable out of $.ajax returned value
type: "GET",
url: "/search",
data: { query: $(this).val() }
});
lastXHRid++; // increment the XHR counter
reqXHR.id = lastXHRid; // attach id to the request
reqXHR.done(function(results, status, respXHR) {
if ( respXHR.id == lastXHRid ){ // compare id of received and last sent requests
showSearchResults(results);
}
});
});
(Edit: I initially suggested tracking the unix timestamp of last sent request, but as #seth-battis suggested in the comments, a sequence number is far enough. As a bonus, I also debugged my sample snippet!)
I am still trying to figure all this out and I am coming across a really weird error.
I was using getJSON but after searching for solutions to this problem, I found that it was better to try to use the AJAX function (for error capturing -> which isnt firing).
Using breakpoints in firebug, if I go slowly through the running code, it works (mostly) fine (just need to change some coordinates for better drawing). But if I let it run at normal speed, it attempts to do the callback before the json object is returned. The firebug console says everything works ok (code 200), but when examining the jobj inside ship object/function it appears to be "undefined or null"
Following the breakpoints, the ajax calls seem to be going to "error" and not "success". But it isn't firing the alert...
Also, the response takes like 300-500ms.... is that normal? or do I need to find a better server?
Edited Code:
var init = (function(){
thisplayer = new player();
jQuery.ajax({type: "GET", url: "shipdata.php", processData: true, data: {shipid:1}, dataType: "json",
success: function(json) {
var pship = new ship(json);
player_ship = $.extend(thisplayer, pship);
starfield = new starfield();
for(var i = 0; i < player_ship.enemytotal; i++) {
$.ajax({
type: "GET",
url: "shipdata.php",
processData: true,
data: {shipid:Math.round((Math.random()*2+2))},
dataType: "json",
success: function(json) {
var enemy = new ship(json);
game.enemies.push(enemy);
},
error: function(x,y,z) {
// x.responseText should have what's wrong
alert(x.responseTest);
}
});
}
game.initialized = true;
},
error: function(x,y,z) {
// x.responseText should have what's wrong
alert(x.responseTest);
}
});
})
..............................
var ship = (function(json){
var self = this;
jobj = jQuery.parseJSON(json.responseText);
self.height = jobj.height;
self.width = jobj.width;
self.xinit = jobj.xinit;
self.yinit = jobj.yinit;
self.speed = jobj.speed;
self.weapons = jobj.weapons;
self.maxlasers = jobj.maxlasers;
self.imagesrc = jobj.imgurl;
self.lasers = [];
self.x = self.xinit;
self.y = self.yinit;
JSON being sent in:
{"height":75,"width":50,"xinit":275,"yinit":525,"speed":3,"weapons":[1,2],"maxlasers":2,"imgurl":"images\/ship.png"}
Live Demo:
http://www.schennshome.net/medicalmmj/practice/index.html (The code is far from being perfect, Im running through it to try and catch the various errors before animating, but cant get past this.)
I've dug through your source code, and the problem is not actually shown in your question. The problem is with this line, which follows your Ajax call:
player_ship = $.extend(thisplayer, game.pship);
game.pship refers to the data returned by the ajax call, but since this is asynchronous, the above line will be evaluated first, which means game.pship will not be defined.
To fix this, you need to include all of the code in your init function that is currently below the ajax call directly in the success callback. This will prevent the code from being evaluated until the ajax call has returned.
The reason that it works with breakpoints is that this interrupts evaluation, which allows the ajax call to complete before game.pship is referenced.
Edit
I'm now getting an error on line 489, stating that player_ship is undefined. This is again because of the evaluation order of async code. The problem is that player_ship is being defined inside the ajax function in init now, but is being referenced in gameLoop, outside of this callback.
This is how I would rewrite gameLoop:
var callback = function() {
game.canvas.clearCanvas();
drawStarfield();
if(player_ship.alive && game.initialized && !(game.loading)) {
drawPlayer();
drawLaser();
drawEnemies();
}
};
if(game.initialized==false) {
init(callback);
} else {
callback();
}
And then amend init to accept a callback method which is called at the bottom of your success callback. This way, if the game has not been initialized (and player_ship is not yet defined), it will be executed after the ajax call.
I have this function that embeds flash :
function embedswfile(target, swf, base, width, height) {//dosomething}
And I want to call the function like this
embedSwf("flashgame",decode("<?=base64_encode($path['location'])?>"),decode("<?=base64_encode($path['base_directory'])?>"),"800","600" )
The idea is that whenever someone looks for any swf inside my website,he wont find anything clean.I will change the encoding algorithm,but this is just temporary. In order for that function to work,whenever I call the function 'decode' it must return a single value. PHP contains
<?php
echo base64_decode($_POST['s']);
?>
I tried this but it still wont work
var globvar;
function processdata(newmsg) {
globvar = newmsg;
}
function decode(s){
$.ajax({type: "POST",
url: "includes/decode.inc.php",
data: "s=" + s,
success:function(newmsg){
processdata(newmsg);
}
});
return globvar;
}
Important:
Forget about using Ajax and encoding, decoding the path. What do you think you gain from it? Security? No. One can figure out that this is bas64 encoded or he just monitors the network traffic and reads the response from the Ajax call.
Just do
embedSwf("flashgame","<? =$path['location']?>"),"<?=$path['base_directory']?>","800","600" )
Really, you cannot prevent someone else seeing the data and are just making things more complicated for you.
(Or you have to decrypt the data with JavaScript.)
(original answer is still correct nevertheless)
Ajax is asynchronous so something like var test = decode(s); will never work. The decode function will return before the Ajax call finishes.
Instead, put your logic into the callback handler. For example, if your code was this before:
var retdata = decode('s');
// here comes code that handles retdata
put the code into a function and call it from the success handler:
function process(retdata) {
// here comes code that handles retdata
}
function decode(s){
$.ajax({type: "POST",
url: "includes/decode.inc.php",
data: "s=" + s,
success:function(newmsg){
process(newmsg);
}
});
}
This seems to be a very common problem to all beginners. You will find a lot of questions here that deal with the same problem.
Update:
It is not nice, but you could change the function to
function decode(s, cb){
$.ajax({type: "POST",
url: "includes/decode.inc.php",
data: "s=" + s,
success:function(data){
cb(data);
}
});
}
and do
decode("<?=base64_encode($path['location'])?>", function(location) {
decode("<?=base64_encode($path['base_directory'])?>", function(dir) {
embedSwf("flashgame",location,dir,"800","600" );
});
});
Update 2:
For completeness, you can make the Ajax call synchronous, by using async: false. Then this will work:
function decode(s){
var ret;
$.ajax({type: "POST",
url: "includes/decode.inc.php",
data: "s=" + s,
async: false,
success:function(newmsg){
ret = newmsg;
}
});
return sync;
}
var val = decode(s);
However, this will block the browser until the Ajax call finished. You have to test whether this matters in your case or not.
Update 3:
You could also change your PHP script to not only accept one parameter but several and process both strings in one go.