Making fetch synchronous in dojo.data
Background
Dojo.data is a fantastic abstraction layer for data stores such as JSON and XML. Dojo.data provides a fetch method which works like a SQL select statement except that it’s asynchronous. Fetch is used by providing your query, a success callback, and a error callback. Once the query is completed the proper callback is called with the returned items. This asynchronous system works great in web applications, allowing the query to be run over the network in the background while not disrupting the user’s experience. This behavior is consistent with the fundamental principles of AJAX.
We, however, are not currently working on a web application. One of our projects has a desktop app component and we’re using Adobe Air and dojo to fulfill this requirement. An asynchronous fetch just doesn’t make sense while we’re doing our data processing. The first thing we tried was a Google search for “dojo.data fetch synchronous”. None of the results gave us information on how to make fetch synchronous, but the third link on that page does give some good information. In that post Nathan Toone explains why fetch is asynchronous and has this to say:
One of the more common questions that I’ve seen is “How can I make this call synchronous?” If you find yourself asking that, you should reexamine what you are trying to accomplish, and change your approach to be more asynchronous. You’ll gain a lot of performance benefits in the long run. Remember, dojo is an Ajax library – not an Sjax library.
But, as the Dalai Lama said, “Learn the rules so you know how to break them properly.” See how to make fetch synchronous after the jump.
How to make fetch synchronous
Fetch is synchronous because of a call to dojo.xhrGet in the method _fetchItems in dojo.data.ItemFileReadStore. As of dojo release 1.2.2 the call was at line 311.
Here is the code in question:
var getArgs = { url: self._jsonFileUrl, handleAs: "json-comment-optional", preventCache: this.urlPreventCache }; var getHandler = dojo.xhrGet(getArgs);
Dojo.xhrGet by default is asynchronous and returns a dojo.Deferred object. This dojo.Deferred object is the same object that is returned from the original call to fetch. Dojo.xhrGet has a synchronous mode, which is turned on simply be adding “sync: true” to the parameters as follows:
var getArgs = { url: self._jsonFileUrl, handleAs: "json-comment-optional", preventCache: this.urlPreventCache, sync: true }; var getHandler = dojo.xhrGet(getArgs);
Fetch will now be synchronous. It would be possible to make this an option to fetch, but we didn’t need this for our application so we didn’t bother.
The take away point is that if you know JavaScript and are familiar with dojo you shouldn’t be afraid of hacking on the dojo source. If you come up with something good you should consider submitting a patch to dojo and they might even include it in the next release.
