📄 jquery.cometd.js
字号:
/** * Copyright 2008 Mort Bay Consulting Pty. Ltd. * Dual licensed under the Apache License 2.0 and the MIT license. * ---------------------------------------------------------------------------- * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http: *www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ---------------------------------------------------------------------------- * Licensed under the MIT license; * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ---------------------------------------------------------------------------- * $Revision: 1503 $ $Date: 2009-03-31 20:41:50 -0500 (Tue, 31 Mar 2009) $ */(function($){ /** * The constructor for a Comet object. * There is a default Comet instance already created at the variable <code>$.cometd</code>, * and hence that can be used to start a comet conversation with a server. * In the rare case a page needs more than one comet conversation, a new instance can be * created via: * <pre> * var url2 = ...; * var cometd2 = new $.Cometd(); * cometd2.init(url2); * </pre> */ $.Cometd = function(name) { var _name = name || 'default'; var _logPriorities = { debug: 1, info: 2, warn: 3, error: 4 }; var _logLevel = 'info'; var _url; var _xd = false; var _transport; var _status = 'disconnected'; var _messageId = 0; var _clientId = null; var _batch = 0; var _messageQueue = []; var _listeners = {}; var _backoff = 0; var _backoffIncrement = 1000; var _maxBackoff = 60000; var _scheduledSend = null; var _extensions = []; var _advice = {}; var _handshakeProps; /** * Returns the name assigned to this Comet object, or the string 'default' * if no name has been explicitely passed as parameter to the constructor. */ this.getName = function() { return _name; }; /** * Configures the initial comet communication with the comet server. * @param cometURL the URL of the comet server */ this.configure = function(cometURL) { _configure(cometURL); }; function _configure(cometURL) { _url = cometURL; _debug('Initializing comet with url: {}', _url); // Check immediately if we're cross domain // If cross domain, the handshake must not send the long polling transport type var urlParts = /(^https?:)?(\/\/(([^:\/\?#]+)(:(\d+))?))?([^\?#]*)/.exec(cometURL); if (urlParts[3]) _xd = urlParts[3] != location.host; // Temporary setup a transport to send the initial handshake // The transport may be changed as a result of handshake if (_xd) _transport = newCallbackPollingTransport(); else _transport = newLongPollingTransport(); _debug('Initial transport is {}', _transport.getType()); }; /** * Configures and establishes the comet communication with the comet server * via a handshake and a subsequent connect. * @param cometURL the URL of the comet server * @param handshakeProps an object to be merged with the handshake message * @see #configure(cometURL) * @see #handshake(handshakeProps) */ this.init = function(cometURL, handshakeProps) { _configure(cometURL); _handshake(handshakeProps); }; /** * Establishes the comet communication with the comet server * via a handshake and a subsequent connect. * @param handshakeProps an object to be merged with the handshake message */ this.handshake = function(handshakeProps) { _handshake(handshakeProps); }; /** * Disconnects from the comet server. * @param disconnectProps an object to be merged with the disconnect message */ this.disconnect = function(disconnectProps) { var bayeuxMessage = { channel: '/meta/disconnect' }; var message = $.extend({}, disconnectProps, bayeuxMessage); // Deliver immediately // The handshake and connect mechanism make use of startBatch(), and in case // of a failed handshake the disconnect would not be delivered if using _send(). _setStatus('disconnecting'); _deliver([message], false); }; /** * Marks the start of a batch of application messages to be sent to the server * in a single request, obtaining a single response containing (possibly) many * application reply messages. * Messages are held in a queue and not sent until {@link #endBatch()} is called. * If startBatch() is called multiple times, then an equal number of endBatch() * calls must be made to close and send the batch of messages. * @see #endBatch() */ this.startBatch = function() { _startBatch(); }; /** * Marks the end of a batch of application messages to be sent to the server * in a single request. * @see #startBatch() */ this.endBatch = function() { _endBatch(true); }; /** * Subscribes to the given channel, performing the given callback in the given scope * when a message for the channel arrives. * @param channel the channel to subscribe to * @param scope the scope of the callback * @param callback the callback to call when a message is delivered to the channel * @param subscribeProps an object to be merged with the subscribe message * @return the subscription handle to be passed to {@link #unsubscribe(object)} */ this.subscribe = function(channel, scope, callback, subscribeProps) { var subscription = this.addListener(channel, scope, callback); // Send the subscription message after the subscription registration to avoid // races where the server would deliver a message to the subscribers, but here // on the client the subscription has not been added yet to the data structures var bayeuxMessage = { channel: '/meta/subscribe', subscription: channel }; var message = $.extend({}, subscribeProps, bayeuxMessage); _send(message); return subscription; }; /** * Unsubscribes the subscription obtained with a call to {@link #subscribe(string, object, function)}. * @param subscription the subscription to unsubscribe. */ this.unsubscribe = function(subscription, unsubscribeProps) { // Remove the local listener before sending the message // This ensures that if the server fails, this client does not get notifications this.removeListener(subscription); var bayeuxMessage = { channel: '/meta/unsubscribe', subscription: subscription[0] }; var message = $.extend({}, unsubscribeProps, bayeuxMessage); _send(message); }; /** * Publishes a message on the given channel, containing the given content. * @param channel the channel to publish the message to * @param content the content of the message * @param publishProps an object to be merged with the publish message */ this.publish = function(channel, content, publishProps) { var bayeuxMessage = { channel: channel, data: content }; var message = $.extend({}, publishProps, bayeuxMessage); _send(message); }; /** * Adds a listener for bayeux messages, performing the given callback in the given scope * when a message for the given channel arrives. * @param channel the channel the listener is interested to * @param scope the scope of the callback * @param callback the callback to call when a message is delivered to the channel * @returns the subscription handle to be passed to {@link #removeListener(object)} * @see #removeListener(object) */ this.addListener = function(channel, scope, callback) { // The data structure is a map<channel, subscription[]>, where each subscription // holds the callback to be called and its scope. // Normalize arguments if (!callback) { callback = scope; scope = undefined; } var subscription = { scope: scope, callback: callback }; var subscriptions = _listeners[channel]; if (!subscriptions) { subscriptions = []; _listeners[channel] = subscriptions; } // Pushing onto an array appends at the end and returns the id associated with the element increased by 1. // Note that if: // a.push('a'); var hb=a.push('b'); delete a[hb-1]; var hc=a.push('c'); // then: // hc==3, a.join()=='a',,'c', a.length==3 var subscriptionIndex = subscriptions.push(subscription) - 1; _debug('Added listener: channel \'{}\', callback \'{}\', index {}', channel, callback.name, subscriptionIndex); // The subscription to allow removal of the listener is made of the channel and the index return [channel, subscriptionIndex]; }; /** * Removes the subscription obtained with a call to {@link #addListener(string, object, function)}. * @param subscription the subscription to unsubscribe. */ this.removeListener = function(subscription) { var subscriptions = _listeners[subscription[0]]; if (subscriptions) { delete subscriptions[subscription[1]]; _debug('Removed listener: channel \'{}\', index {}', subscription[0], subscription[1]); } }; /** * Removes all listeners registered with {@link #addListener(channel, scope, callback)} or * {@link #subscribe(channel, scope, callback)}. */ this.clearListeners = function() { _listeners = {}; }; /** * Returns a string representing the status of the bayeux communication with the comet server. */ this.getStatus = function() { return _status; }; /** * Sets the backoff period used to increase the backoff time when retrying an unsuccessful or failed message. * Default value is 1 second, which means if there is a persistent failure the retries will happen * after 1 second, then after 2 seconds, then after 3 seconds, etc. So for example with 15 seconds of * elapsed time, there will be 5 retries (at 1, 3, 6, 10 and 15 seconds elapsed). * @param period the backoff period to set * @see #getBackoffIncrement() */ this.setBackoffIncrement = function(period) { _backoffIncrement = period; }; /** * Returns the backoff period used to increase the backoff time when retrying an unsuccessful or failed message. * @see #setBackoffIncrement(period) */ this.getBackoffIncrement = function() { return _backoffIncrement; }; /** * Returns the backoff period to wait before retrying an unsuccessful or failed message. */ this.getBackoffPeriod = function() { return _backoff; }; /** * Sets the log level for console logging. * Valid values are the strings 'error', 'warn', 'info' and 'debug', from * less verbose to more verbose. * @param level the log level string */ this.setLogLevel = function(level) { _logLevel = level; }; /** * Registers an extension whose callbacks are called for every incoming message * (that comes from the server to this client implementation) and for every * outgoing message (that originates from this client implementation for the * server). * The format of the extension object is the following: * <pre> * { * incoming: function(message) { ... }, * outgoing: function(message) { ... } * }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -