Backbone.JS<\/a> had multiple template files it needed to download, if and only if the files hadn\u2019t already been downloaded before. <\/p>\nWhile I suppose I could have relied on browser caching, I wanted to manage the requests in JavaScript. The trick was that at any given time, a request might include one or more template files, and some of the request might have already been made, or in progress.<\/p>\n
Here\u2019s the queuing function:<\/p>\n
(function<\/span>() {\n var<\/span> allFiles = {};\n var<\/span> allResults = {};\n\n var<\/span> queueRequest = function<\/span> (path, files, options) {\n options = options || {};\n files = $.isArray(files) ? files : [files];\n \n \/\/ this will contain all of the deferreds that will be <\/span>\n \/\/ wrapped with a `when` deferred<\/span>\n var<\/span> when = [];\n \/\/ might want to override some defaults...<\/span>\n var<\/span> ajaxOpt = $.extend({\n dataType: 'json'<\/span>,\n type: 'GET'<\/span>\n }, options.ajax || {});\n\n \/\/ go thru each file<\/span>\n $.each(files, function<\/span> (i, file) {\n var<\/span> xhr;\n \/\/ if we've not seen it before<\/span>\n if<\/span> (typeof<\/span> allFiles[file] === 'undefined'<\/span>) {\n \/\/ kick it off<\/span>\n xhr = $.ajax(path + file, ajaxOpt).done(function<\/span> (data) {\n \/\/ store the file results in the hash index<\/span>\n allResults[file] = data;\n });\n \/\/ keep the deferred for later use<\/span>\n allFiles[file] = xhr;\n \/\/ and keey this for later<\/span>\n when.push(xhr);\n } else<\/span> {\n \/\/ already seen this, so just pack it on<\/span>\n when.push(allFiles[file]);\n }\n });\n \/\/ return all of the built up deferreds as a <\/span>\n \/\/ single when. this will then wait until <\/span>\n \/\/ all are satisfied<\/span>\n return<\/span> $.when.apply(this<\/span>, when).done(function<\/span> () {\n if<\/span> ($.isFunction(options.done)) {\n options.done.call(this<\/span>, allResults);\n }\n }).fail(options.error);\n };\n\n window.Queue = queueRequest;\n})();<\/pre>\nQueuing is easy enough:<\/p>\n
Queue(app_url("api\/template\/"<\/span>), templates, {\n done: function<\/span> (allFiles) {\n _.each(templates, function<\/span> (n) {\n \/\/ compile only if needed<\/span>\n if<\/span> (typeof<\/span> allTemplates[n] === 'undefined'<\/span>) {\n allTemplates[n] = _.template(allFiles[n]);\n }\n });\n if<\/span> (typeof<\/span> callback === 'function'<\/span>) {\n callback.call(context, allTemplates);\n }\n }\n});<\/pre>\nallTemplates<\/strong> is a list of compiled underscore templates stored elsewhere.<\/p>\n