(hoofbeats) Uses a queue and a cache to query musicbrainz.
authorSalvatore Iovene <salvatore@iovene.com>
Tue, 5 Feb 2013 14:31:22 +0000 (16:31 +0200)
committerSalvatore Iovene <salvatore@iovene.com>
Tue, 5 Feb 2013 14:31:22 +0000 (16:31 +0200)
examples/hoofbeats/javascripts/musicbrainz.js

index adaae9e..58e324e 100644 (file)
 /* vi: set et sw=4 ts=4 si: */
 (function(win, $) {
     var musicbrainz = function() {
-        this.baseUrl = 'http://musicbrainz.org/ws/2/';
-        this.fmtArg = 'fmt=json';
+        this._baseUrl = 'http://musicbrainz.org/ws/2/';
+        this._fmtArg = 'fmt=json';
+        this._interval = undefined;
+        this._queue = [];
+        this._url_cache = {};
+
+
+        /* Internal methods to perform XHR requests. */
+
+        this._get = function(request) {
+            var self = this;
+
+            if (request.url in self._url_cache) {
+                request.deferred.resolve(self._url_cache[request.url]);
+            } else {
+                $.getJSON(request.url)
+                .done(function(data, statusText, xhr) {
+                    self._url_cache[request.url] = data;
+                    request.deferred.resolve(data);
+                })
+                .error(function(xhr) {
+                    if (xhr.status === 503) {
+                        self._enqueue(request); // put it back in the queue
+                    }
+                }); 
+            }
+
+            return request.deferred.promise();
+        };
+
+
+        /* Internal methods for the handling of the request queue */
+
+        this._startQueue = function() {
+            var self = this;
+
+            if (self._interval === undefined) {
+                self._interval = setInterval(function() {
+                    self._dequeue();
+                }, 2000);
+            }
+        };
+
+        this._stopQueue = function() {
+            clearInterval(this._interval);
+            this._interval = undefined;
+        };
+
+        this._enqueue = function(request) {
+            this._queue.push(request);
+        };
+
+        this._dequeue = function() {
+            var request = this._queue.shift();
+            if (request !== undefined) {
+                this._get(request);
+            }
+        };
+
+
+        /* Public methods */
 
         this.getArtist = function(q) {
             var self = this,
-                lookup_url = self.baseUrl + 'artist/?query="' + q +
-                             '"&' + self.fmtArg;
-                deferred = new $.Deferred();
+                lookup_url = self._baseUrl + 'artist/?query="' + q +
+                             '"&' + self._fmtArg,
+                lookup_deferred = new $.Deferred(),
+                returned_deferred = new $.Deferred();
 
             if (q !== undefined) {
-                $.getJSON(lookup_url).done(function(data) {
+                if (self._interval === undefined) {
+                    self._startQueue();
+                }
+
+                self._enqueue({url: lookup_url, deferred: lookup_deferred});
+                lookup_deferred.done(function(data) {
                     if (data.count > 0) {
-                        artist_url = self.baseUrl + 'artist/' +
-                                     data.artist[0].id + '?' + self.fmtArg;
-                        $.getJSON(artist_url).done(function(data) {
-                            deferred.resolve(data);
+                        var artist_url = self._baseUrl + 'artist/' +
+                                         data.artist[0].id + '?' + self._fmtArg,
+                            artist_deferred = new $.Deferred();
+
+                        self._get({url: artist_url, deferred: artist_deferred});
+                        artist_deferred.done(function(data) {
+                            returned_deferred.resolve(data);
                         });
                     } else {
-                        deferred.reject();
+                        returned_deferred.reject();
                     }
                 });
             } else {
-                deferred.reject();
+                returned_deferred.reject();
             }
 
-            return deferred.promise();
+            return returned_deferred.promise();
         };
     }