Javascript Synchronization with JSON Requests - javascript

How can I make sure that a piece of code has executed completely before executing another? I am sending some ajax requests to a server and then using the returned data to generate the rest of the webpage. the things is, is that i need to have all that data in the webpage to proceed with the rest of the code as that code will affect what has been generated and, that code, runs before the json requests and all of that have finished... is there any way I can make sure this does not happen? I managed to solve it by performing the requests and then asking the user to press a button but that is a total no-sense way of doing it.
Any ideas?
Here is some code: The problem is that the second line is executed before the first (there are many calls to similar JSON functions).
$.getJSON(url, function(data){ $("#mycontent").append("..... stuff here...... create loads of dibs with class set to mydivclass"); });
...
$("div.mydivclass").hide();
Unforunately I cannot use the ajax synchronous property because: "dataType: "jsonp" requests do not support synchronous operations"

If you are using jQuery 1.5+ you can make use of deferreds to solve your issue:
function first_ajax_request() {
return jQuery.ajax(
// Your settings here
success: success_function_1
);
}
function second_ajax_request() {
return jQuery.ajax(
// Your settings here
success: success_function_2
);
}
function final_sucess_callback() {
// Do all your display work.
}
jQuery.when(first_ajax_request(),
second_ajax_request()).then(final_success_callback);
There is an excellent article on the topic that you should read up on as well by Eric Hynds. He gives some examples of exactly the kind of problem you are trying to solve.

jquery requests are asynchonize by default , so your code does not wait for the response , so you have no guarantee that code after request will execute after the response , so you can set the request synchronize by set the async property false , now the request is synchronize and you can gurantee the rest of the code will execute after the response from the server ,
like this .
$.ajax({
url: "page.php",
processData: false,
data: xmlDocument,,
async:false,
success: handleResponse
});

Related

How to run getJSON synchronously? [duplicate]

GOAL: What I'm after is to get data from database and refresh main.php (more evident through draw_polygon) every time something is added in database (after $.ajax to submit_to_db.php).
So basically I have a main.php that will ajax call another php to receive an array that will be saved to database, and a json call another php to return an array will be used by main.php.
$(document).ready(function() {
get_from_db();
$('#button_cancel').click(function(){
$.ajax({
url: 'submit_to_db.php',
type: 'POST',
data: {list_item: selected_from_list},
success: function(result){
...
get_from_db();
}
});
});
function get_from_db(){
$.getJSON('get_from_db.php', function(data) {
...
draw_polygon(data);
});
}
});
In my case, what I did was a get_from_db function call for getJSON to actually get data from database, with the data to be used to draw_polygon. But is that how it should be done? I'm a complete newbie and this is my first time to try getJSON and ajax too to be honest. So my question: How does asynchronous work actually? Is there another workaround for this instead of having to call function get_from_db with getJSON (it isn't synchronous, is it? is that why it doesn't update the page when it isn't within a function?) All the time - like $.ajax with async: false (I couldn't get it to work by the way). My approach is working, but I thought maybe there are other better ways to do it. I'd love to learn how.
To make it more clearer, here's what I want to achieve:
#start of page, get data from database (currently through getJSON)
Paint or draw in canvas using the data
When I click the done button it will update the database
I want to AUTOMATICALLY get the data again to repaint the changes in canvas.
Since $.getJSON() uses ajax configurations, just set the global ajax configs:
// Set the global configs to synchronous
$.ajaxSetup({
async: false
});
// Your $.getJSON() request is now synchronous...
// Set the global configs back to asynchronous
$.ajaxSetup({
async: true
});
Asynchronusly does mean the Request is running in the background, and calls your function back when it got a response. This method is best if you want to have a result but allow to use your app within the request. If you want to have a direct response, take a look at a synchron request. this request will pause script execution until it got a response, and the user can not do anything until the response was recieved. You can toggle it via:
async: false,
So for example:
$.ajax({
url: "myurl",
async: false,
...
})
$.getJSON(), doesn't accept a configuration, as it says in the docs it's a shorthand version of:
$.ajax({
dataType: "json",
url: url,
data: data,
success: success
});
So just rewrite your request in terms of that and async:false will work just as you expect.
$.getJSON() is a shorthand notation for $.ajax() which can be configured to be synchronous (see jQuery.getJSON and JQuery.ajax):
$.ajax({
dataType: "json",
url: url,
data: data,
async: false,
success: function(data) {
...
draw_polygon(data);
}
});
Try to avoid synchronous calls though. Quote from jQuery doc (see async prop):
Cross-domain requests and dataType: "jsonp" requests do not support
synchronous operation. Note that synchronous requests may temporarily
lock the browser, disabling any actions while the request is active.
You might want to try jQuery Deferreds like this:
var jqxhr = $.getJSON(url);
jqxhr.done(function(data) {
...
draw_polygon(data);
});

Javascript ajax request callback without waiting for response

I know we can make a javascript ajax request from some server and it either receives the response or gives timeout error after some time.
Let's consider this scenario when we don't want to wait for the request rather the server would send a response(or we can say it would be another request from server to client) async at any time after getting the request and then call a javascript CB function with the response.
I am looking for ideas for how to go about it mainly supporting all modern browsers and if possible not relying on any 3rd party plugin except may be jQuery.
The main feature of Ajax is that it IS asynchronous by default, and your program will continue to run without waiting for the response. So unless I'm misreading your question, it is what you need.
If you use jquery, then you pass in a callback function that will execute only when the server sends back a response. You can specify a timeout in the settings, though I'm not sure what the maximum time you can provide without getting a timeout error. But it will be several seconds, at least.
You can even specify different callbacks for success and fail as follows (adapted from the jquery ajax API, but added a timeout of 5 seconds):
var request = $.ajax({
url: "http://www.some.url/",
method: "GET",
data: { some : stuff },
dataType: "html",
timeout: 5000
});
request.done(function( data ) {
console.log( "SUCCESS: " + data );
});
request.fail(function() {
console.log( "Request failed");
});
I came across this question after 4 years. I dont remember in what context I asked this but for anyone who has the same query:
Http is a request/response protocol. Which means the client sends a request and the server responds to that request with some message/data. Thats the end of the story for that request.
In order for the server to trigger something on the clientside we will have to use something that keeps the connection to the server rather than ending the communication after getting the response. Socket.io is bi directional event driven library that solves this problem.
To update a cart (PHP Session storage and reserve the stock of items in database) on my online shop, I simply add a timeout of 100ms after calling it and remove Success/Error callback.
$.ajax({
url: 'http://www.some.url/',
method: 'GET',
data: {
some : 'stuff'
},
dataType: 'html',
timeout: 100
});
Note : It doesn't matter if some requests didn't arrive, because when the order is saved, an update of the whole cart is sent with a callback.
If your query needs acknowledge, don't use that solution !
I believe your question is similar to this
by Paul Tomblin. I use the answer provided by gdoron, which is also marked as the best solution, and also the comment by AS7K.
$.ajax({
url: "theURL",
data: theData
});
NB: No async parameter provided.

Use data from ajax call without using async: false

I'm pretty new to JS/ajax and was a bit confused on ajax data/success returns.
I have the following ajax code. I want it to run the code in succes: after the ajax call has received the json from the imgur api.
It is only working for me with async: false. I thought the bit in success: would only run after the data has been retrieved, but for some reason data is null if aysnc is true.
I've read a lot of SO answers/jQuery documentation but I can't seem to figure out how to get it to not hang the browser with async: false
This code might be running 100+ times on a page (i.e. reddit.com/r/pics with 100 links loaded on one page), so async: false is not only bad practice but also renders the page unusable for 5 to 6 seconds, which is unacceptable.
I've tried making ajax a var then calling that var .success(function(data) ...); but it still does not work. I've also tried replacing success with complete.
It all only ever works with async: false
Any suggestions would be greatly appreciated!
Thanks!
$.ajax({
type: "GET",
url: "https://api.imgur.com/3/gallery/" + hash,
dataType: "json",
headers:{
'Authorization':'Client-ID c606aeeec9ca098'
},
async: false,
success: function(data) {
if(data.data.is_album == true) {
if(data.data.images_count == 1){
el[j].href = el[j].href.replace(/(http(s)?:\/\/)?(www\.)?(m\.)?imgur.com\/gallery\/.*/, data.data.images[0].link);
}else{
el[j].href = el[j].href.replace(/(http(s)?:\/\/)?(www\.)?(m\.)?imgur.com\/gallery\//, "https://imgur.com/a/");
}
}
else{
el[j].href = el[j].href.replace(/(.*)?(http(s)?:\/\/)?(www\.)?(m\.)?imgur.com\/.*/, data.data.link);
}
}
});
You might find the jQuery Deferred object (Promises interface) to be helpful. It allows you to do stuff like:
var promise = $.ajax("/myServerScript1");
function getStuff() {
return $.ajax("/myServerScript2");
}
promise.then(getStuff).then(function(myServerScript2Data){
// Do something with myServerScript2Data
});
Resource (this is well written and a necessary read for anyone using AJAX):
http://www.htmlgoodies.com/beyond/javascript/making-promises-with-jquery-deferred.html
I can't see what doesn't work on your code but I can tell you what is not recommended.
Always have a failure handler : You have to put a function in the fail field of your request object. If you don't, you will not be able to see any errors.
Keep the test simple : You should begin by only displaying the value of the request result instead making some calculation with it. This way you can debug ONLY the request call and you are sure that the problem doesn't came from the calculation code
Use Promises API : As previously pointed by the #gibberish, the modern way to do what you want is to use Promises. You can use jQuery's promises or any other like ES6 Promises (that one requires a compilation time for most of browsers)

Correct usage of Deferred objects and Promises in my jQuery AJAX requests

I need to load JSON data from a server using JavaScript and/or jQuery with an AJAX request.
I have several other scripts on the same page load that will need to access this JSON data after it is loaded so it is important that it is loaded before my other code runs.
I would like to utilize and use the newer Promises and Deferred Objects
Also this question and example code shows 1 instnce of loading JSON data fro my app but in the final result I will duplicate this to load 3-4 different sets of JSON data from 3-4 AJAX requests. So it is important to get this right so that all my requests can use the same code.
A little background on the data and its use might help to understand my goal a little better...
I am building a Project Management app which has a main core JavaScript object/file. I then have sub-module JavaScript object/files which work together with the core file.
Some of these include:
Core ProjectManagement.js
ProjectManagement.User.module.js
ProjectManagement.Milestones.module.js
ProjectManagement.Tags.module.js
ProjectManagement.Tasks.module.js
ProjectManagement.Files.module.js
ProjectManagement.Activity.module.js
Now in my core PM JavaScript file I will need access to a userlist JSON object. THe userlist should be loaded on page load with 1 AJAX request made from the ProjectManagement.User.module.js object/file and then cached the JSON result to a variable inside the ProjectManagement.js object/file.
The next time that nany of the sub-module JavaScript code needs to access the userlist JSON, it will simply get the data from the cached variable instead of making an additional AJAX request to get the data over and over for each sub-module.
This same situation applies to all the related data such as Milestones, Tags, ACL Permissions, and more.
For this reason I feel the JavaScript Promises and Deferred objects are a good route to go instead of callback functions. I need to load all these JSON objects from multiple AJAX requests and have them all load before all my sub-module JS code starts calling for them and causing problems.
In my attempt to use Promises and Deferred objects, this is what I have from the code below...
var deferredLoadTaskObject = $.Deferred();
On AJAX success I call the resolve() function of the deferred object
deferredLoadTaskObject.resolve();
On AJAX failure I call the reject() function of the deferred object deferredLoadTaskObject.reject();
Now to be honest, I am not sure that I even need to do the above calls. I know that all jQuery AJAX requests are in themselves a Promise so this code above might be simply doing the same thing over again 2 times?
I much prefer the explicit calls that the code above makes as it seems more cut and dry to show what it is doing. However as mentioned I am not sure that it is required or not?
Am I doing it all wrong?
My code below shows a simplified/cleaned up version of 1 of my AJAX request which uses the Promise/Deferred code from above.
I have a specific function that has 1 single job which is to make the AJAX request and return the result. I would like to continue this approach as it is clean and easy to understand and follow.
I can simply have a function like ajaxLoadTaskData(task_id) for each of my data sets that I need (milestones, users, tags, etc...).
I then have var taskDataAjax = ajaxLoadTaskData(task_id); which assigns the AJAX request to the var taskDataAjax and I then can call taskDataAjax.done(), taskDataAjax.fail(), and taskDataAjax.always() on it which inside of each of these I can then call deferredLoadTaskObject.resolve() and deferredLoadTaskObject.reject() to satisfy the Promise/Deferred Objects
Short Summary Version...
If you can't be bothered to read above fully...
I simply need help in making sure I am using the Promise/Deferred Objects correctly make my AJAX requests which will in the end be making several different AJAX requests and on there completion will assign data to variables to be used among several JavaScript sub-modules/objects/files in my large JS Application.
If I am doing it wrong, please kindly provide some help in making it correct
One area of concern is my use of calling var deferredLoadTaskObject = $.Deferred(); and then calling deferredLoadTaskObject.resolve() and deferredLoadTaskObject.reject() inside the AJAX response callbacks.
I am not sure if this is correct use or if I should not be calling these since jQuery AJAX request are by default already a Promise of some sort.
JavaScript function that makes AJAX request to load JSON data and returns it
ajaxLoadTaskData: function(task_id) {
return $.ajax({
type: 'POST',
async: true,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
url: getTaskRecordUrl,
data: {
action: 'load-task-record',
task_id: task_id
},
});
},
Testing use of Promises and Deferred Objects
var deferredLoadTaskObject = $.Deferred();
JavaScript which calls the above function for the AJAX request...
// Get Task Data from AJAX Request
var taskDataAjax = ajaxLoadTaskData(task_id);
taskDataAjax.done(function(response) {
// JSON response from AJAX request
var taskRecordJson = response;
deferredLoadTaskObject.resolve();
});
taskDataAjax.fail(function(response) {
// AJAX request failed
console.log('response', 'response');
deferredLoadTaskObject.reject();
});
taskDataAjax.always(function(response) {
});

execute a PHP script from Ajax without expecting an answer (and no daemons)

I hope you can help me with this issue:
My sistem runs over Zend Framework, I have installed jQuery in it's latest version. I have an input that receives a file and it makes an Ajax call when changes, and I want that call made in the background, without expecting any response (because that script will send an email when finished). My ajax call is like this:
var formData = new FormData();
formData.append('file', $(this).get(0).files[0]);
$.ajax({
url: 'uploadaddresses.php',
type: 'POST',
data: formData,
dataType: 'json',
async:true,
processData: false,
contentType: false,
beforeSend: function(){
bootbox.alert("You've made your petition correctly. When finished, an email will be sent to you.")
},
error: function(err) {}
});
return false;
Although, the call waits for a response (even FireBug shows me that uploadaddresses.php is still executing...). What i'm doing wrong? How should I do it best? I want to avoid using daemons and system calls, because system restrictions...
Thank you very much in advance :)
If you're wanting uploadaddresses.php to return an HTTP response immediately but continue processing, take a look at pcntl_fork in PHP.
Here's the main doc page: http://php.net/manual/en/function.pcntl-fork.php
Here's a good example that you might want to follow: http://php.net/manual/en/function.pcntl-fork.php#94338
Create a success method for the ajax call and have something like this:
console.log("Done");
This way you know if is complete and successful but only if you are looking at the dev tools. Unless you specify output it should not continue to run after the call has been made. Maybe you have an error in your PHP code?
EDIT: If you can't get this resolved you may want to post your PHP page as well.

Categories