📄 jquery.cometd.js
字号:
_notifyListeners('/meta/unsubscribe', failureMessage);
_notifyListeners('/meta/unsuccessful', failureMessage);
}
function _messageSuccess(message)
{
if (message.successful === undefined)
{
if (message.data)
{
// It is a plain message, and not a bayeux meta message
_notifyListeners(message.channel, message);
}
else
{
_debug('Unknown message {}', JSON.stringify(message));
}
}
else
{
if (message.successful)
{
_debug('Publish successful');
_notifyListeners('/meta/publish', message);
}
else
{
_debug('Publish unsuccessful');
_notifyListeners('/meta/publish', message);
_notifyListeners('/meta/unsuccessful', message);
}
}
}
function _messageFailure(xhr, message)
{
_debug('Publish failure');
var failureMessage = {
successful: false,
failure: true,
channel: message.channel,
request: message,
xhr: xhr,
advice: {
action: 'none',
interval: 0
}
};
_notifyListeners('/meta/publish', failureMessage);
_notifyListeners('/meta/unsuccessful', failureMessage);
}
function _notifyListeners(channel, message)
{
// Notify direct listeners
_notify(channel, message);
// Notify the globbing listeners
var channelParts = channel.split("/");
var last = channelParts.length - 1;
for (var i = last; i > 0; --i)
{
var channelPart = channelParts.slice(0, i).join('/') + '/*';
// We don't want to notify /foo/* if the channel is /foo/bar/baz,
// so we stop at the first non recursive globbing
if (i == last) _notify(channelPart, message);
// Add the recursive globber and notify
channelPart += '*';
_notify(channelPart, message);
}
}
function _notify(channel, message)
{
var subscriptions = _listeners[channel];
if (subscriptions && subscriptions.length > 0)
{
$.each(subscriptions, function(index, subscription)
{
// Subscriptions may come and go, so the array may have 'holes'
if (subscription)
{
try
{
_debug('Notifying subscription: channel \'{}\', callback \'{}\'', channel, subscription.callback.name);
subscription.callback.call(subscription.scope, message);
}
catch (x)
{
// Ignore exceptions from callbacks
_warn('Exception during execution of callback \'{}\' on channel \'{}\' for message {}, exception: {}', subscription.callback.name, channel, JSON.stringify(message), x);
}
}
});
}
}
function _resetBackoff()
{
_backoff = 0;
}
function _increaseBackoff()
{
if (_backoff < _maxBackoff) _backoff += _backoffIncrement;
}
var _error = this._error = function(text, args)
{
_log('error', _format.apply(this, arguments));
};
var _warn = this._warn = function(text, args)
{
_log('warn', _format.apply(this, arguments));
};
var _info = this._info = function(text, args)
{
_log('info', _format.apply(this, arguments));
};
var _debug = this._debug = function(text, args)
{
_log('debug', _format.apply(this, arguments));
};
function _log(level, text)
{
var priority = _logPriorities[level];
var configPriority = _logPriorities[_logLevel];
if (!configPriority) configPriority = _logPriorities['info'];
if (priority >= configPriority)
{
if (window.console) window.console.log(text);
}
}
function _format(text)
{
var braces = /\{\}/g;
var result = '';
var start = 0;
var count = 0;
while (braces.test(text))
{
result += text.substr(start, braces.lastIndex - start - 2);
var arg = arguments[++count];
result += arg !== undefined ? arg : '{}';
start = braces.lastIndex;
}
result += text.substr(start, text.length - start);
return result;
}
function newLongPollingTransport()
{
return $.extend({}, new Transport('long-polling'), new LongPollingTransport());
}
function newCallbackPollingTransport()
{
return $.extend({}, new Transport('callback-polling'), new CallbackPollingTransport());
}
/**
* Base object with the common functionality for transports.
* The key responsibility is to allow at most 2 outstanding requests to the server,
* to avoid that requests are sent behind a long poll.
* To achieve this, we have one reserved request for the long poll, and all other
* requests are serialized one after the other.
*/
var Transport = function(type)
{
var _maxRequests = 2;
var _requestIds = 0;
var _cometRequest = null;
var _requests = [];
var _packets = [];
this.getType = function()
{
return type;
};
this.send = function(packet, comet)
{
if (comet)
_cometSend(this, packet);
else
_send(this, packet);
};
function _cometSend(self, packet)
{
if (_cometRequest !== null) throw 'Concurrent comet requests not allowed, request ' + _cometRequest.id + ' not yet completed';
var requestId = ++_requestIds;
_debug('Beginning comet request {}', requestId);
var request = {id: requestId};
self.deliver(packet, request);
_cometRequest = request;
}
function _send(self, packet)
{
var requestId = ++_requestIds;
_debug('Beginning request {}, {} other requests, {} queued requests', requestId, _requests.length, _packets.length);
var request = {id: requestId};
// Consider the comet request which should always be present
if (_requests.length < _maxRequests - 1)
{
_debug('Delivering request {}', requestId);
self.deliver(packet, request);
_requests.push(request);
}
else
{
_packets.push([packet, request]);
_debug('Queued request {}, {} queued requests', requestId, _packets.length);
}
}
this.complete = function(request, success, comet)
{
if (comet)
_cometComplete(request);
else
_complete(this, request, success);
};
function _cometComplete(request)
{
var requestId = request.id;
if (_cometRequest !== request) throw 'Comet request mismatch, completing request ' + requestId;
// Reset comet request
_cometRequest = null;
_debug('Ended comet request {}', requestId);
}
function _complete(self, request, success)
{
var requestId = request.id;
var index = $.inArray(request, _requests);
// The index can be negative the request has been aborted
if (index >= 0) _requests.splice(index, 1);
_debug('Ended request {}, {} other requests, {} queued requests', requestId, _requests.length, _packets.length);
if (_packets.length > 0)
{
var packet = _packets.shift();
if (success)
{
_debug('Dequeueing and sending request {}, {} queued requests', packet[1].id, _packets.length);
_send(self, packet[0]);
}
else
{
_debug('Dequeueing and failing request {}, {} queued requests', packet[1].id, _packets.length);
packet[0].onFailure(packet[1], 'error');
}
}
}
this.abort = function()
{
$.each(_requests, function(index, request)
{
_debug('Aborting request {}', request.id);
if (request.xhr) request.xhr.abort();
});
if (_cometRequest)
{
_debug('Aborting comet request {}', _cometRequest.id);
if (_cometRequest.xhr) _cometRequest.xhr.abort();
}
_cometRequest = null;
_requests = [];
_packets = [];
};
};
var LongPollingTransport = function()
{
this.deliver = function(packet, request)
{
request.xhr = $.ajax({
url: packet.url,
type: 'POST',
contentType: 'text/json;charset=UTF-8',
beforeSend: function(xhr)
{
xhr.setRequestHeader('Connection', 'Keep-Alive');
return true;
},
data: JSON.stringify(packet.messages),
success: function(response) { packet.onSuccess(request, response); },
error: function(xhr, reason, exception) { packet.onFailure(request, reason, exception); }
});
};
};
var CallbackPollingTransport = function()
{
var _maxLength = 2048;
this.deliver = function(packet, request)
{
// Microsoft Internet Explorer has a 2083 URL max length
// We must ensure that we stay within that length
var messages = JSON.stringify(packet.messages);
var urlLength = packet.url.length + messages.length;
// Let's stay on the safe side and use 2048 instead of 2083
// also because we did not count few characters among which
// the parameter name 'message'
if (urlLength > _maxLength)
{
var x = packet.messages.length > 1 ?
'Too many bayeux messages in the same batch resulting in message too big ' +
'(' + urlLength + ' bytes, max is ' + _maxLength + ') for transport ' + this.getType() :
'Bayeux message too big (' + urlLength + ' bytes, max is ' + _maxLength + ') ' +
'for transport ' + this.getType();
// Keep the semantic of calling response callbacks asynchronously after the request
_setTimeout(function() { packet.onFailure(request, 'error', x); }, 0);
}
else
{
$.ajax({
url: packet.url,
type: 'GET',
dataType: 'jsonp',
jsonp: 'jsonp',
beforeSend: function(xhr)
{
xhr.setRequestHeader('Connection', 'Keep-Alive');
return true;
},
data:
{
// In callback-polling, the content must be sent via the 'message' parameter
message: messages
},
success: function(response) { packet.onSuccess(request, response); },
error: function(xhr, reason, exception) { packet.onFailure(request, reason, exception); }
});
}
};
};
};
/**
* The JS object that exposes the comet API to applications
*/
$.cometd = new $.Cometd(); // The default instance
})(jQuery);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -