Reputation: 192447
I'm working with some government data published via Socrata's SODA api.
This API provides a way to retrieve rows via a REST call. The API allows limited parameterization of the query - basically you can do a full text search, and nothing else. I cannot find a way to shape the data returned - for example only return certain columns of the data.
As a result, basically I can only get all rows and all columns of each data view. This is ok, I guess, but I'd like to cache it - memoize it to use the underscore term.
Is there a pattern for memoization of ajax calls with jQuery?
EDIT: To give you an idea of what I'm talking about, here's what I'm doing currently.
function onclick(event) {
var $t = $(event.currentTarget);
var itemId = $t.attr('data-itemid');
var url = getRestUrl(itemId);
if (typeof datacache[itemId] === "undefined") {
$.ajax({
url : url,
cache : true,
type : "GET",
dataType : "json",
error : function(xhr,status,error) {
raiseError(error);
},
success : function(response, arg2, xhr) {
datacache[itemId] = response;
doSomethingWithTheData(url, itemId);
}});
}
else {
doSomethingWithTheData(url, itemId);
}
}
// then, doSomethingWithTheData() simply references datacache[itemId]
This seems like it's faster though I haven't measured it. What I really want to know is, is there a common pattern that does something like this, that I can employ, so that everyone who reads the code will immediately see what I'm doing??
Upvotes: 6
Views: 2310
Reputation: 5196
You would only cache ajax requests that you know won't change, like the Facebook SDF for example. It seems like in your example, you're requesting something UI related that might be inappropriate to cache? Otherwise, you might try something like this:
var store = {};
/**
* Memoized $.getScript
*
* Cache one script response per url
* Reference, see http://msdn.microsoft.com/en-us/magazine/gg723713.aspx
*
* @example $.memoizedGetScript( url ).then( successCallback, errorCallback );
* @param {String} url
* @param {Function} callback (optional)
* @returns {*}
*/
$.memoizedGetScript = function(url, callback) {
var callback = callback || {};
store.cachedScripts = {};
if (!store.cachedScripts[url]) {
store.cachedScripts[url] = $.Deferred(function(d) {
$.getScript(url).then(
d.resolve(),
d.reject()
);
}).promise();
}
return store.cachedScripts[url].done(callback);
};
Upvotes: 0
Reputation: 1566
I'm not necessarily the best expert for Javascript question, but I might be able to help you with your use of SODA.
If you're looking for more flexibility in your queries, and you can do an HTTP POST, you could look at using our query syntax to do a more targeted query: http://dev.socrata.com/querying-datasets. Our query syntax is fairly complex, but I can help you figure out how to structure your query if you hit any snags.
Unfortunately, since that'd require a POST, you'll need to break out of the XHR cross-domain lockbox by going through a proxy or something similar.
Also, FYI, we're working on a whole new syntax that'll allow you to specify queries as URL parameters, so you'll be able to perform simple requests such as /resources/agencies?acronym=CIA
or /resources/agencies?$where='budget > 10000000'
. It should be pretty awesome.
Upvotes: 0
Reputation: 107508
You might be able to do something like is done with autocomplete lookups (this is very much from memory, but you'll get the idea):
var searchCache = {}, searchXhr = null;
function Search(term) {
if (term in searchCache) {
return doSomethingWithTheData(searchCache[term]);
}
if (searchXhr != null) {
searchXhr.abort();
}
searchXhr = $.ajax({
url : url,
cache : true,
type : "GET",
dataType : "json",
error : function(xhr, status, error) {
raiseError(error);
},
success : function(response, arg2, xhr) {
searchCache[term] = response;
if (xhr == searchXhr) {
doSomethingWithTheData(response);
searchXhr = null;
}
}
});
}
Upvotes: 3