148 lines
4.8 KiB
JavaScript
148 lines
4.8 KiB
JavaScript
/*
|
|
* Copyright (c) 2012, Andy Janata
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
|
* provided that the following conditions are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions
|
|
* and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of
|
|
* conditions and the following disclaimer in the documentation and/or other materials provided
|
|
* with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
|
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
/**
|
|
* AJAX long polling library.
|
|
*
|
|
* @author Andy Janata (ajanata@socialgamer.net)
|
|
*/
|
|
|
|
cah.longpoll = {};
|
|
cah.longpoll.TIMEOUT = 45 * 1000;
|
|
// cah.longpoll.TIMEOUT = 30 * 1000;
|
|
|
|
/**
|
|
* Backoff when there was an error.
|
|
*
|
|
* @type {number}
|
|
*/
|
|
cah.longpoll.INITIAL_BACKOFF = 500;
|
|
|
|
/**
|
|
* Backoff after a successful request.
|
|
*
|
|
* @type {number}
|
|
*/
|
|
cah.longpoll.NORMAL_BACKOFF = 1;
|
|
|
|
/**
|
|
* Current backkoff.
|
|
*
|
|
* @type {number}
|
|
*/
|
|
cah.longpoll.Backoff = cah.longpoll.INITIAL_BACKOFF;
|
|
cah.longpoll.Resume = true;
|
|
cah.longpoll.ErrorCodeHandlers = {};
|
|
cah.longpoll.EventHandlers = {};
|
|
|
|
/**
|
|
* Start a long polling operation.
|
|
*/
|
|
cah.longpoll.longPoll = function() {
|
|
cah.log.debug("starting long poll");
|
|
$.ajax({
|
|
cache : false,
|
|
complete : cah.longpoll.complete,
|
|
error : cah.longpoll.error,
|
|
success : cah.longpoll.done,
|
|
timeout : cah.longpoll.TIMEOUT,
|
|
url : cah.LONGPOLL_URI,
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Called when a long polling operation completes, success or failure. Will start another poll
|
|
* unless the previous one ended in a terminal failure (likely because the server restarted and we
|
|
* no longer have a session on it).
|
|
*/
|
|
cah.longpoll.complete = function() {
|
|
if (cah.longpoll.Resume) {
|
|
setTimeout("cah.longpoll.longPoll()", cah.longpoll.Backoff);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Called when a long polling operation completes successfully. Dispatches the events to the
|
|
* appropriate handler.
|
|
*
|
|
* @param {Array}
|
|
* data_list A list of events to process.
|
|
*/
|
|
cah.longpoll.done = function(data_list) {
|
|
cah.log.debug("long poll done", data_list);
|
|
|
|
var data_list_work;
|
|
// we need to handle non-array data, too, so just make it look like an array
|
|
if (data_list[cah.$.LongPollResponse.TIMESTAMP] || data_list[cah.$.LongPollResponse.ERROR]) {
|
|
data_list_work = {};
|
|
data_list_work[0] = data_list;
|
|
} else {
|
|
data_list_work = data_list;
|
|
}
|
|
|
|
for ( var index in data_list_work) {
|
|
var data = data_list_work[index];
|
|
if (data[cah.$.LongPollResponse.ERROR]) {
|
|
// TODO cancel any timers or whatever we may have, and disable interface
|
|
// this probably should be done in the appropriate error code handler because we may not
|
|
// want to always be that extreme.
|
|
var errorCode = data[cah.$.LongPollResponse.ERROR_CODE];
|
|
if (cah.longpoll.ErrorCodeHandlers[errorCode]) {
|
|
cah.longpoll.ErrorCodeHandlers[errorCode](data);
|
|
} else {
|
|
cah.log.error(cah.$.ErrorCode_msg[errorCode]);
|
|
}
|
|
} else {
|
|
// FIXME giant hack
|
|
if (data[cah.$.LongPollResponse.PLAY_TIMER]) {
|
|
$("#current_timer").text(data[cah.$.LongPollResponse.PLAY_TIMER] / 1000);
|
|
}
|
|
var event = data[cah.$.LongPollResponse.EVENT];
|
|
if (cah.longpoll.EventHandlers[event]) {
|
|
cah.longpoll.EventHandlers[event](data);
|
|
} else {
|
|
cah.log.error("Unhandled event " + event);
|
|
}
|
|
}
|
|
}
|
|
|
|
// reset the backoff to normal when there's a successful operation
|
|
cah.longpoll.Backoff = cah.longpoll.NORMAL_BACKOFF;
|
|
};
|
|
|
|
/**
|
|
* Called when a long polling operation completes with an error.
|
|
*/
|
|
cah.longpoll.error = function(jqXHR, textStatus, errorThrown) {
|
|
// TODO deal with this somehow
|
|
cah.log.debug(textStatus);
|
|
if (cah.longpoll.Backoff < cah.longpoll.INITIAL_BACKOFF) {
|
|
cah.longpoll.Backoff = cah.longpoll.INITIAL_BACKOFF;
|
|
} else {
|
|
cah.longpoll.Backoff *= 2;
|
|
}
|
|
cah.log
|
|
.error("Error communicating with server. Will try again in " + (cah.longpoll.Backoff / 1000)
|
|
+ " second" + (cah.longpoll.Backoff != 1000 ? "s" : "") + ".");
|
|
};
|