How do I load JSON data synchronously with d3.js? - json

When my site first initializes, it queries a server to get back some data. I can't lay anything out on the page until this data gets back. With d3.js, I can use d3.json() to get my data, but because it's asynchronous, I need to put the entire page logic in the callback function. How do I request the data and wait for it to come back?

You're basically doing it the only way. The callback function has to be the one initiating the rest of your code. You don't need all your code in the callback function though, you can introduce indirection. So the callback function will call another function inside which would be what is currently in your callback function.

Using synchronous requests in JavaScript is not recommended as it blocks the whole thread and nothing gets done in the meantime. The user can also not interact well with the webpage.
If it is really what you want, you can do the following (using jQuery):
var jsonData;
jQuery.ajax({
dataType: "json",
url: "jsondatafile.json",
async: false
success: function(data){jsonData = data}
});
However it is not recommended, even by jQuery, as explained here the jQuery.ajax() documentation:
The first letter in Ajax stands for "asynchronous," meaning that the operation occurs in parallel and the order of completion is not guaranteed. The async option to $.ajax() defaults to true, indicating that code execution can continue after the request is made. Setting this option to false (and thus making the call no longer asynchronous) is strongly discouraged, as it can cause the browser to become unresponsive.
As a final note, I don't see what prevents you from using whatever function there is in the success attribute in an asynchronous way. Most of the times changing your design to use async requests will be worth it. By experience, debugging a page that uses synchronous requests is a pain (especially when the requests don't get answered...).

Related

How to extend AFNetworking 2.0 to perform request combining

I have a UI where the same image URL could be requested by several UIImageViews at varying times. Obviously if a request from one of them has finished then returning the cached version works as expected. However, especially with slower networks, I'd like to be able to piggy-back requests for an image URL onto any currently running/waiting HTTP request for the same URL.
On an HTTP server this called request combining and I'd love to do the same in the client - to combine the different requests for the same URL into a single request and then callback separately to each of the callers). The requests for that URL dont happen to start at the same time.
What's the best way to accomplish this?
I think re-writing UIImageView+AFNetworking might be the easiest way:
check the af_sharedImageRequestOperationQueue to see if it has an operation with the same request
if I do already have an operation in the queue or running then add myself to some list of callbacks/blocks to be called on success/failure
if I don't have the operation, then create it as normal
in the setCompletionBlockWithSuccess to call each of the blocks in turn.
Any simpler alternatives?
I encountered a similar problem and decided that your way was the most straightforward. One added bit of complexity is that these downloads require special credentials and so must go through their own operation queue. Here's the code from my UIImageView category to check whether a particular URL is inflight:
NSUInteger foundOperation = [[ConnectionManager sharedConnectionManager].operationQueue.operations indexOfObjectPassingTest:^BOOL(AFHTTPRequestOperation *obj, NSUInteger idx, BOOL *stop) {
BOOL URLAlreadyInFlight = [obj.request.URL.absoluteString isEqualToString:URL.absoluteString];
if (URLAlreadyInFlight) {
NSBlockOperation *updateUIOperation = [NSBlockOperation blockOperationWithBlock:^{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.image = [[ImageCache sharedImageCache] cachedImageForURL:URL];
}];
}];
//Makes updating the UI dependent on the completion of the matching operation.
[updateUIOperation addDependency:obj];
}
return URLAlreadyInFlight;
}];
Were you able to come up with a better solution?
EDIT: Well, it looks like my method of updating the UI just can't work, as the operation's completion blocks are run asynchronously, so the operation finishes before the blocks are run. However, I was able to modify the image cache to be able to add callbacks for when certain URLs are cached, which seems to work correctly. So this method will properly detect when certain URLs are in flight and be able to take action with that knowledge.

Wait for jQuery ajax response to finish updating the page before allowing another ajax call

I've read many posts about this but still can't wrap my head around fixing my problem. I've looked at jQuery.when but not sure how to use it. I get data from the server via ajax and then it updates the page. Sometimes, it might take a few seconds depending on how much data is being returned. I don't want that same ajax function to run until all html has loaded on the page. Is that possible?
I have a timer to run a function that calls an ajax request.
setInterval( "update()", 25000 );
This is the ajax inside the update function
$.ajax({
type: "POST",
url: "/ajax/modify.php",
data: "id="+ id +"& action="+ act,
success: function(response){
//update the html on the page
}
});
There is a way for the user to get more posts by clicking on a link. Well problem is, if they click that link to get more posts and the timer happens right after, it refreshes the page and interrupts the users request and reloads the div container with what was there before. So I need it to wait until the response has completed and the page has been updated before allowing more requests.
An example what be appreciated.
JQuery's ajax method returns a promise, which you can use to attach callbacks. You can store away this promise into a variable. On success/fail of the function, you can clear the variable. This way you know if a request is currently active or not. Just make sure the variable is outside the function scope or it won't do anything to help you. For example:
var currentRequest = null;
function doUpdate() {
// don't do anything if there's an active request
if (currentRequest)
return;
currentRequest = $.ajax({
type: "POST",
url: "/ajax/modify.php",
data: "id="+ id +"& action="+ act
}).then(function(response) {
// do your UI updates here.
}).always(function() {
// whether the call succeeds or not, still clear out the request
// so that the next call into the function makes a new request
currentRequest = null;
});
}
have a look at this SO question jQuery deferreds and promises - .then() vs .done()
jQuery Deffered Object
doing async:false kills the purpose of it, you can fire the next ajax request in the success call back of the first one but that is not a clean approach IMO

AJAX call in a continuous loop?

I want to create some kind of AJAX script or call that continuously will check a MySQL database if any new messages has arrived. When there is a new message in the database, the AJAX script should invoke a kind of alert box or message box.
I’m not quite a AJAX expert (yet anyway) and have Googled around to find a solution but I’m having a hard time to figure out where to begin. I imagine that it is kind of the same method that an AJAX chat is using to see if any new chat-message has been send.
I’ve also tried to search for AJAX (httpxmlrequest) call in a continuously and infinity loop but still haven’t got a solution yet.
I hope there is someone, which can help me with such a AJAX script or maybe nudge me in the right direction.
Thanks
Sincerely
Mestika
Step 1 - You need a server-side page that you can call that checks to see if something new has arrived.
Step 2 - You could adapt the sequential AJAX request script from here (it uses jQuery to simplify the AJAX requests):
http://www.stevefenton.co.uk/Content/Blog/Date/201004/Blog/AJAX-and-Race-Conditions/
Currently, this script is for queuing a list of sequential AJAX requests, but you could use it to continually check by changing it like this...
var InfiniteAjaxRequest = function (uri) {
$.ajax({
url: uri,
success: function(data) {
// do something with "data"
if (data.length > 0) {
alert(data);// Do something sensible with it!
}
InfiniteAjaxRequest (uri);
},
error: function(xhr, ajaxOptions, thrownError) {
alert(thrownError);
}
});
};
InfiniteAjaxRequest ("CheckForUpdate.php");
What are the benefits of using this script?
Well, rather than checking every "x" seconds, it will only check once the previous request has been received, so it chains the requests. You could add in a delay to throttle this constant request, which I would highly recommend you do - otherwise you will be hitting your site with way too much traffic. You would add that delay in AFTER you've done something with the response, but BEFORE you call back into "InfiniteAjaxRequest".
Here's your nudge:
Get one of the available JavaScript frameworks (jQuery seems to be the most common, but there are others)
flip though the documentation on the AJAX methods it provides, choose a method for your task that seems appropriate
build a request to your site that fetches the info and reacts on the response (shows a message box or updates some part of your page), wrap that in a function
make sure request errors do not go unnoticed by implementing an error handler
check out setInterval() to call that function you've just made repeatedly
final step: make sure that the interval will be stopped in case of an error condition (or provide a on/off button for the user, even) so the server is not hammered needlessly
There is a technique called Comet where-by your client-side script would instantiate a HTTP request which remains open for a long time. The server can then push data into the response as they happen. It's a technique to deliver a push notification.
The Wikipedia link has more information on real-world implementations.
Instead of polling the server with AJAX calls you could also use push technology (COMET).
This way you can push the results to the client(s) as soon as the server is done with it's work.
There are many frameworks available like:
JQuery plugin
Cometd
Atmosphere (if your on java)

Asynchronous Ajax call in SCORM API

I am creating a javascript API for SCORM 2004 4th Edition. For those who don't know about SCORM, basically it is an API standard that eLearning courses can use to communicate with an LMS (Learning Management System). Now the API has to have the following method:
Initialize(args)
GetValue(key)
SetValue(key, value)
Terminate(args)
Commit(args)
GetDiagnostic(args)
GetErrorString(args)
GetLastError()
Now Initialize has to be called before anything else, and Terminate must the last. GetValue/SetValue can be called anywhere in between there. What I am doing is in the Initialize method I am getting some JSON from a web service and storing that in the API (to be used when using the GetValue/SetValue methods later). The problem I am coming across is that the AJAX call via jQuery is asynchronous, so the Initialize method call could be done before the JSON is loaded. With that being the way it is, a call to GetValue after calling Initialize could cause unexpected issues b/c the JSON that GetValue uses isn't there yet. My question is this: What can I do to ensure that the JSON is loaded before the GetValue/SetValue methods are called? I know the simple answer is to make it synchronous, but that is not advised mostly, and it doesn't seem to want to do that for me. Here is my code regarding that:
function GetJSON(){
var success = false;
$.ajaxSetup({async:false}); //should make it synchronous
$.getJSON("http://www.mydomain.com/webservices/scorm.asmx/SCORMInitialize?
learnerID=34&jsoncallback=?",
function(data){
bind(data);
success = true;
}
);
return success;
}
function bind(data){
this.cmi = eval("(" + data.d + ")");
$.ajaxSetup({async:true}); //should make it asynchronous again
}
Does anyone have any ideas? I would really appreciate it!
You've articulated the problem well. After the SCO calls Initialize, the CMI data needs to be immediately available for the SCO to make subsequent GetValue calls. However, making synchronous AJAX calls isn't advised, if there is a hangup in the request, it can lock up the entire browser until the request returns or times out. The solution is to pre-load all of the required data before the SCO is loaded. In our SCORM Engine implementation, we preload all of the data (CMI and sequencing) when the player is launched and then use a background process to periodically commit dirty data as the learner progresses through the course. It can get a bit tricky to ensure that all data is properly persisted when dealing with the combinations of possible window launching and exit scenarios, but it's certainly possible. You will want to avoid any requests to the server from within a SCORM API call as SCOs will often flood the LMS with big batches of calls. Making server requests within those calls can seriously degrade the learner's experience and place a performance burden on the server.
Mike
The way we approached this problem was to queue the CMI data in the API when the SCO is launched. We first navigate to a launch page that loads the CMI data into the API's queue, and then the laucnch page actually launches the SCO. When the SCO calls intialize, we just move the data into the CMI.

How does facebook, gmail send the real time notification?

I have read some posts about this topic and the answers are comet, reverse ajax, http streaming, server push, etc.
How does incoming mail notification on Gmail works?
How is GMail Chat able to make AJAX requests without client interaction?
I would like to know if there are any code references that I can follow to write a very simple example. Many posts or websites just talk about the technology. It is hard to find a complete sample code. Also, it seems many methods can be used to implement the comet, e.g. Hidden IFrame, XMLHttpRequest. In my opinion, using XMLHttpRequest is a better choice. What do you think of the pros and cons of different methods? Which one does Gmail use?
I know it needs to do it both in server side and client side.
Is there any PHP and Javascript sample code?
The way Facebook does this is pretty interesting.
A common method of doing such notifications is to poll a script on the server (using AJAX) on a given interval (perhaps every few seconds), to check if something has happened. However, this can be pretty network intensive, and you often make pointless requests, because nothing has happened.
The way Facebook does it is using the comet approach, rather than polling on an interval, as soon as one poll completes, it issues another one. However, each request to the script on the server has an extremely long timeout, and the server only responds to the request once something has happened. You can see this happening if you bring up Firebug's Console tab while on Facebook, with requests to a script possibly taking minutes. It is quite ingenious really, since this method cuts down immediately on both the number of requests, and how often you have to send them. You effectively now have an event framework that allows the server to 'fire' events.
Behind this, in terms of the actual content returned from those polls, it's a JSON response, with what appears to be a list of events, and info about them. It's minified though, so is a bit hard to read.
In terms of the actual technology, AJAX is the way to go here, because you can control request timeouts, and many other things. I'd recommend (Stack overflow cliche here) using jQuery to do the AJAX, it'll take a lot of the cross-compability problems away. In terms of PHP, you could simply poll an event log database table in your PHP script, and only return to the client when something happens? There are, I expect, many ways of implementing this.
Implementing:
Server Side:
There appear to be a few implementations of comet libraries in PHP, but to be honest, it really is very simple, something perhaps like the following pseudocode:
while(!has_event_happened()) {
sleep(5);
}
echo json_encode(get_events());
The has_event_happened function would just check if anything had happened in an events table or something, and then the get_events function would return a list of the new rows in the table? Depends on the context of the problem really.
Don't forget to change your PHP max execution time, otherwise it will timeout early!
Client Side:
Take a look at the jQuery plugin for doing Comet interaction:
Project homepage: http://plugins.jquery.com/project/Comet
Google Code: https://code.google.com/archive/p/jquerycomet/ - Appears to have some sort of example usage in the subversion repository.
That said, the plugin seems to add a fair bit of complexity, it really is very simple on the client, perhaps (with jQuery) something like:
function doPoll() {
$.get("events.php", {}, function(result) {
$.each(result.events, function(event) { //iterate over the events
//do something with your event
});
doPoll();
//this effectively causes the poll to run again as
//soon as the response comes back
}, 'json');
}
$(document).ready(function() {
$.ajaxSetup({
timeout: 1000*60//set a global AJAX timeout of a minute
});
doPoll(); // do the first poll
});
The whole thing depends a lot on how your existing architecture is put together.
Update
As I continue to recieve upvotes on this, I think it is reasonable to remember that this answer is 4 years old. Web has grown in a really fast pace, so please be mindful about this answer.
I had the same issue recently and researched about the subject.
The solution given is called long polling, and to correctly use it you must be sure that your AJAX request has a "large" timeout and to always make this request after the current ends (timeout, error or success).
Long Polling - Client
Here, to keep code short, I will use jQuery:
function pollTask() {
$.ajax({
url: '/api/Polling',
async: true, // by default, it's async, but...
dataType: 'json', // or the dataType you are working with
timeout: 10000, // IMPORTANT! this is a 10 seconds timeout
cache: false
}).done(function (eventList) {
// Handle your data here
var data;
for (var eventName in eventList) {
data = eventList[eventName];
dispatcher.handle(eventName, data); // handle the `eventName` with `data`
}
}).always(pollTask);
}
It is important to remember that (from jQuery docs):
In jQuery 1.4.x and below, the XMLHttpRequest object will be in an
invalid state if the request times out; accessing any object members
may throw an exception. In Firefox 3.0+ only, script and JSONP
requests cannot be cancelled by a timeout; the script will run even if
it arrives after the timeout period.
Long Polling - Server
It is not in any specific language, but it would be something like this:
function handleRequest () {
while (!anythingHappened() || hasTimedOut()) { sleep(2); }
return events();
}
Here, hasTimedOut will make sure your code does not wait forever, and anythingHappened, will check if any event happend. The sleep is for releasing your thread to do other stuff while nothing happens. The events will return a dictionary of events (or any other data structure you may prefer) in JSON format (or any other you prefer).
It surely solves the problem, but, if you are concerned about scalability and perfomance as I was when researching, you might consider another solution I found.
Solution
Use sockets!
On client side, to avoid any compatibility issues, use socket.io. It tries to use socket directly, and have fallbacks to other solutions when sockets are not available.
On server side, create a server using NodeJS (example here). The client will subscribe to this channel (observer) created with the server. Whenever a notification has to be sent, it is published in this channel and the subscriptor (client) gets notified.
If you don't like this solution, try APE (Ajax Push Engine).
Hope I helped.
According to a slideshow about Facebook's Messaging system, Facebook uses the comet technology to "push" message to web browsers. Facebook's comet server is built on the open sourced Erlang web server mochiweb.
In the picture below, the phrase "channel clusters" means "comet servers".
Many other big web sites build their own comet server, because there are differences between every company's need. But build your own comet server on a open source comet server is a good approach.
You can try icomet, a C1000K C++ comet server built with libevent. icomet also provides a JavaScript library, it is easy to use as simple as:
var comet = new iComet({
sign_url: 'http://' + app_host + '/sign?obj=' + obj,
sub_url: 'http://' + icomet_host + '/sub',
callback: function(msg){
// on server push
alert(msg.content);
}
});
icomet supports a wide range of Browsers and OSes, including Safari(iOS, Mac), IEs(Windows), Firefox, Chrome, etc.
Facebook uses MQTT instead of HTTP. Push is better than polling.
Through HTTP we need to poll the server continuously but via MQTT server pushes the message to clients.
Comparision between MQTT and HTTP: http://www.youtube.com/watch?v=-KNPXPmx88E
Note: my answers best fits for mobile devices.
One important issue with long polling is error handling.
There are two types of errors:
The request might timeout in which case the client should reestablish the connection immediately. This is a normal event in long polling when no messages have arrived.
A network error or an execution error. This is an actual error which the client should gracefully accept and wait for the server to come back on-line.
The main issue is that if your error handler reestablishes the connection immediately also for a type 2 error, the clients would DOS the server.
Both answers with code sample miss this.
function longPoll() {
var shouldDelay = false;
$.ajax({
url: 'poll.php',
async: true, // by default, it's async, but...
dataType: 'json', // or the dataType you are working with
timeout: 10000, // IMPORTANT! this is a 10 seconds timeout
cache: false
}).done(function (data, textStatus, jqXHR) {
// do something with data...
}).fail(function (jqXHR, textStatus, errorThrown ) {
shouldDelay = textStatus !== "timeout";
}).always(function() {
// in case of network error. throttle otherwise we DOS ourselves. If it was a timeout, its normal operation. go again.
var delay = shouldDelay ? 10000: 0;
window.setTimeout(longPoll, delay);
});
}
longPoll(); //fire first handler