How to stop in jquery $.post? - javascript

i want to stop executing javascript code after the line "return false",but it don't.
my english is poor. if anyone understand me,please improve my question thank you!
$('#category-list input').blur(function(){
var $$ = $(this), $p = $$.prev();
if ($$.val() != $p.html()) {
var data = {'key':$$.attr('name'),'value':$$.val()};
$.post('<?php echo Url::to(['field']); ?>', data).done(function(result){
if (result != 'ok'){
alert(result);
return false; /*i need it stop at here!!!!!! but it not*/
}
});
alert(3);
$p.html($$.val());
}
$$.hide();
$p.show();
});

The short answer is you can't stop a parent function inside an ajax completion function because that will most likely fire after the function itself is finished executing. Regardless, its 2 separate events
$.post is an asynchronous ajax request. This means, that the .done() part of the function will execute AFTER the ajax request comes back.
However, the rest of the function runs synchronously, meaning every (or some) line of code after .post will run before the server even responds. To get around this, you need to re-architect how you execute your functions.
let's examine this with a basic function:
function getSomeAjax() {
//1 - the alert will execute first
alert('first line of execution');
//2 - the post request will execute second
$.post('someUrl', data).done(function(result){
if (result != 'ok'){
alert('post request complete');
//this will execute randomly whenever the server responds.
//it could be in 1 second, 5 seconds, or 20 seconds
}
});
//3
alert('last line of execution');
}
looking at the example above, you should move any logic that is dependent on the server response into the if clause. Otherwise it will execute regardless of your post request

Related

unlike following queries first ajax query returns undefined

Have a bit of an issue here. I checked the different answers which seemed related to my problem but cannot seem to get this working.
I've got a page with a link like so :
View
And here's the javascript
var queryResult;
function getData(id, callbackfn){
$.ajax({
type:"POST",
url:"http://url/to/query",
data:{id: id },
success: function(data){
callbackfn(data);
},
error: function(){
return "err";
}
});
}
function showData(id){
getData(id, Callback);
if(queryResult)
{
alert("Yahoooooo !");
}
else
{
alert("Nope !!!");
}
}
function Callback(data){
queryResult = data.length;
}
When clicked for the first time the link launches the alert box and I get "Nope !!!" but any subsequent click will show a "Yahoooooo !"
If I reload the page then again "Nope !!!" for the first time and then it's fine afterwards. So it seems that queryResult is undefined on the first call but first call only. Any idea ?
Thanx
Put your control in Callback function
function Callback(data){
queryResult = data.length;
if(queryResult)
{
alert("Yahoooooo !");
}
else
{
alert("Nope !!!");
}
}
You're using .ajax
this method is asyncronous by default.
So you call "getData" then your Data is loaded.
While it is loaded you check if queryResult exists
Then the data has been loaded and your global flag is set
(At the moment you are checking if the previous request was successful)
The ajax call executes ansynchronously. Therefore when you call getData(), the method call returns instantly (and the ajax call is executing in another thread). This means the first time you click the link, there won't be anything in queryresult because the ajax call hasn't had time to finish before you hit your if block, but the subsequent times there (probably) will be, assuming the call has finished before the next time you click the link.
If you have any logic, such as that if block which depends on the data being returned from the ajax call, you must include it in (or call it from) your callback function.
So in this case you must move the block:
if(queryResult)
{
alert("Yahoooooo !");
}
else
{
alert("Nope !!!");
}
from the getData to the Callback function.

Is it a good practice to make ajax call after ajax callback?

I am wondering is it a good practice to make an ajax in an ajax callback function (could be called nested ajax calls?) ? Anyway here is my example
ajax.js
$(document).ready(function() {
$('#button').click(function() {
var string = 'some string';
$.post('ajax-call.php',
{
string: string
}, function(result) {
if(result == 'success') {
// Second ajax call if result returned is success
$.post('second-ajax.php',
{
variable: 'Some Variable'
}, function(second_result) {
if(second_result == 'yes') {
// Do some thing when the second result returned 'yes'
} else {
// Alert error or something
}
});
} else {
// If first result is not success, show a message
}
});
});
});
So basically I have two separate php file that is called on different time, if the first ajax call returned 'success' then proceed to call the second ajax call. Or should I be using one ajax call, one php script, and decide what to do depending on the result of callback ? example below.
ajax2.js
$(document).ready(function() {
$('#button').click(function() {
var string = 'some string';
$.post('ajax-call.php',
{
string: string
}, function(result) {
if(result == 'success') {
// Do something
} else if(result == 'unsuccessful') {
// If first result is not success, show a message
} else {
// Show error message
}
});
});
});
*Note: both php script are quite a heavy and long script which the first script is codes for validating the ajax call, and if everything is validated correctly, proceed to second ajax call to process the datas into database and so on. The first example will make the script much cleaner and neater, but I am wondering if it is good practice to use nested ajax like that ?
All suggestions and comments are greatly welcome. Thank you in advance for enlightening me on this.
Answering the question:
If both ajax calls are two different services and the second call depends on the first response, I'll do it.
If they are standalone services, I'll work with promises and do the callback when both are resolved.
Maybe is not focused on the question itself, but I see weird to make two server calls for just one real action (the second one).
What I'll do is to make just one call. If the validation doesn't pass, return the error. If it passes, call the other php on the server side and return a vlid response to the client.
Server should do the same job, but you save one data transmission from client to server.
That's just an opinion. I hope it helped you.

Why my setInterval function doesn't stop

I need to write a setInterval function in javascript. Thi is the code:
var myTimer=setInterval(function(){
var time=0;
$.ajax({
url:'...'
type: "POST",
dataType:"",
success: function (response) {
if(response=="true" || time>=10000){
clearInterval(myTimer);
}
time=time+1000;
},
error: function () {
alert("FAIL");
}
});
},1000);
I don't know why It doesn't stop in clearInterval. Anyone can help me?
You've claimed that the code does "come in the 'if'", so I assume the clearInterval call is actually being made.
Given that, the most likely explanation is that the interval is being cleared (after all, select isn't broken), but before the first "true" response, you've already made more than one ajax call, and the other ones you're seeing are ones scheduled before the interval was cleared.
E.g., your code runs and:
Fires off ajax call #1, which takes more than a second to complete
Fires off ajax call #2
Ajax call #1 completes but isn't "true"
Fires off ajax call #3
Ajax call #2 completes and is "true", clearing the interval
Ajax call #3 completes
Mixing two separate asynchronous intervals (one via setInterval and one via ajax) is asking for trouble.
If the goal is to make the request once a second and stop when you get back "true", I would have the success handler schedule the next call, e.g.:
(function() {
var time = 0;
var started = 0;
start();
function start() {
started = Date.now();
$.ajax({
url: '...'
type: "POST",
dataType: "",
success: function(response) {
if (response != "true") {
// Schedule the next call to occur one second after we
// started the previous call; or almost immediately if
// the call took more than a second to complete
setTimeout(start, Math.max(0, 1000 - (Date.now() - started)));
}
time = time + 1000;
},
error: function() {
alert("FAIL");
}
});
}
})();
Let me illustrate the expected and the actual scenarios to make things clearer.
Scenario #1
The image below shows the case where all your ajax requests complete before one second. You will notice that ajax callback success (or error) functions will execute only before clearInterval (which is what you always expect).
Scenario #2
When some of your ajax requests take more than one second (which is probably what happens), then your ajax callbacks can fire before / after / before-and-after the clearInterval, which makes you feel that your setInterval doesn't stop.
Note that your time variable is useless because it's a function-scoped variable that you initialize to 0 every function call. And even if it's a global variable, it'll only clear the interval in the 11th success function callback, and nothing guarantees how long these 11 successful requests will take.
Solution
As T.J. Crowder suggested, it's better to schedule the next ajax call in the success callback of the previous one, which guarantees that your ajax requests fire sequentially (only one at a time).
Note: Because you edited your question after his answer, then you'll also need to edit the if condition like this:
success: function(response) {
if (response != "true" && time < 10000) {
setTimeout(start, Math.max(0, 1000 - (Date.now() - started)));
}
}

JavaScript: Continue with function after another function call finishes

Edits: http://jsfiddle.net/vol7ron/wQZdM/
The fiddle should be used to help illustrate what I'm trying to do and what's happening. The sub-selects should be populated with the second option value.
Original Question:
Not sure the best way to ask. I'm creating a testing script to autofill inputs on a form.
It includes a series of drop-down select boxes, which populate other select options in an onChange event. When trying to auto-populate the form, the sub-selects don't have any options.
console.clear();
// non-select inputs
$(':input:not([type="hidden"],[type="button"])').each(function(){
$(this).val($(this).attr('name')) // test value is simple input's name
});
// select inputs
var count=0, cutoff=7500;
$('select').each(function(){
var t = $(this);
var c = t.children('option');
while( c.length <= 1 && count < cutoff){
count++;
c = $(this).children('option'); // tried not using the cache'd variable
if (!(count % 10))
console.log(count, c.length, "No Options"); // debugging -- never exists early
setTimeout(function(){},0); // not really doing anything
}
t.val( c.eq(1).val() ); // set value to second option value
t.trigger('change'); // calls the onChange even if it doesnt exist
});
// verify it does have data
console.log($('#sub-select').children('option').length); // does have options
There's an AJAX call in the change event. I could modify the callback, but this is just a simple set script for testing, that is run from console. Any ideas?
Not really sure what your code is trying to do
But answering the question How to continue with function after another function call finishes :-
assuming you have a list of functions which are all asynchronous you can nest them to continue
to the next asynchronous function ...
asyncCall(callback1) {
callback1(callback2) {
callback2(...)
}
}
Checkout https://github.com/caolan/async for some elegant ways to do this
this example calls all functions in order even though they are asynchronous.
async.series([
function(callback){
setTimeout(function(){
call_order.push(1);
callback(null, 1);
}, 25);
},
function(callback){
setTimeout(function(){
call_order.push(2);
callback(null, 2);
}, 50);
},
function(callback){
setTimeout(function(){
call_order.push(3);
callback(null, 3,3);
}, 15);
}
1) Use Synchronous AJAX request http://api.jquery.com/jQuery.ajax/
var html = $.ajax({
url: "some.php",
async: false
}).responseText;
2) Instead of using the .each use .eq(index) and just call it in order.
function FakeEach(idx) {
if(idx >= 7500) return;
var $obj = $('select').eq(idx);
if($obj.length == 0) return;
...
$obj.trigger('change');
window.setTimeout(function() { FakeEach(idx++); }, 0);
}
Your problem is that you are starting an AJAX request in the function, and expect that the response arrives before the function ends. As long as you are using an asynchronous request, this will never happen. You have to exit your function before the code that handles the response can run. Javascript is single threaded, so as long as your function is running, no other code can run.
The solution to the problem is to put the code that uses the data in the success callback function that is called after the response has arrived. Eventhough you usually write that function inside the function that makes the AJAX call, it's a separate function that will run later.
If you really need the data in the same function as the AJAX call, you would need to make a synchronous request. This is a killer for the user experience, though, as the entire browser freezes while it is waiting for the response.

Help on getting data to output when a variable changes

I am trying to write a JavaScript interface for an Api, but I can not figure out this issue. I have code to call an ajax request:
mooshark.request('userInfoFromID', {
userID : '20991'
});
That code creates an Ajax request. When it starts, it sets an internal variable to true (to indicate that it is running). Then on the next line I have this:
var data = mooshark.response();
alert(data);
The response function is as follows:
response: function () {
if(this.running == false){
return "done";
} else if (this.running == true){
alert("Running");
setTimeout(this.response, 3000);
}
}
It outputs (in this order) Running. undefined. (JSON response). Running. Not once does it output "done". Is there a way to return "done" when this.running becomes true? I would like to mention that this.running will not always be the same request time. I know there is always the option of wrapping all my code inside the onCompleat function in the ajax request, but I want to have that as a last resort.
Thanks!
This is not possible without freezing the browser.
Whenever your code is running, the browser UI will be completely frozen.
If you want the call to wait for the server to reply, the browser will need to be competely frozen. (which is not a good idea)
Since most of the time you're calling response() through setTimeout(), a return value isn't really useful.
But -- you're likely never setting your 'running' variable to false. You might post more code here (the AJAX response handling code, for example). Also: what exactly are you trying to accomplish by returning / alerting "running" and "done"?

Categories

Resources