jquery.cometd.js

来自「jetty SERVER連接資料庫用的軟體」· JavaScript 代码 · 共 1,436 行 · 第 1/4 页

JS
1,436
字号
         * }
         * Both properties are optional, but if they are present they will be called
         * respectively for each incoming message and for each outgoing message.
         * </pre>
         * @param name the name of the extension
         * @param extension the extension to register
         * @return true if the extension was registered, false otherwise
         * @see #unregisterExtension(name)
         */
        this.registerExtension = function(name, extension)
        {
            var existing = false;
            $.each(_extensions, function(index, extension)
            {
                if (extension.name == name)
                {
                    existing = true;
                    return false;
                }
            });
            if (!existing)
            {
                _extensions.push({
                    name: name,
                    extension: extension
                });
                _debug('Registered extension \'{}\'', name);
                return true;
            }
            else
            {
                _info('Could not register extension with name \'{}\': another extension with the same name already exists');
                return false;
            }
        };

        /**
         * Unregister an extension previously registered with
         * {@link #registerExtension(name, extension)}.
         * @param name the name of the extension to unregister.
         * @return true if the extension was unregistered, false otherwise
         */
        this.unregisterExtension = function(name)
        {
            var unregistered = false;
            $.each(_extensions, function(index, extension)
            {
                if (extension.name == name)
                {
                    _extensions.splice(index, 1);
                    unregistered = true;
                    _debug('Unregistered extension \'{}\'', name);
                    return false;
                }
            });
            return unregistered;
        };

        /**
         * Starts a the batch of messages to be sent in a single request.
         * @see _endBatch(deliverMessages)
         */
        function _startBatch()
        {
            ++_batch;
        }

        /**
         * Ends the batch of messages to be sent in a single request,
         * optionally delivering messages present in the message queue depending
         * on the given argument.
         * @param deliverMessages whether to deliver the messages in the queue or not
         * @see _startBatch()
         */
        function _endBatch(deliverMessages)
        {
            --_batch;
            if (_batch < 0) _batch = 0;
            if (deliverMessages && _batch == 0 && !_isDisconnected())
            {
                var messages = _messageQueue;
                _messageQueue = [];
                if (messages.length > 0) _deliver(messages, false);
            }
        }

        function _nextMessageId()
        {
            return ++_messageId;
        }

        /**
         * Converts the given response into an array of bayeux messages
         * @param response the response to convert
         * @return an array of bayeux messages obtained by converting the response
         */
        function _convertToMessages(response)
        {
            if (response === undefined) return [];
            if (response instanceof Array) return response;
            if (response instanceof String || typeof response == 'string') return eval('(' + response + ')');
            if (response instanceof Object) return [response];
            throw 'Conversion Error ' + response + ', typeof ' + (typeof response);
        }

        function _setStatus(newStatus)
        {
            _debug('{} -> {}', _status, newStatus);
            _status = newStatus;
        }

        function _isDisconnected()
        {
            return _status == 'disconnecting' || _status == 'disconnected';
        }

        /**
         * Sends the initial handshake message
         */
        function _handshake(handshakeProps)
        {
            _debug('Starting handshake');
            _clientId = null;

            // Start a batch.
            // This is needed because handshake and connect are async.
            // It may happen that the application calls init() then subscribe()
            // and the subscribe message is sent before the connect message, if
            // the subscribe message is not held until the connect message is sent.
            // So here we start a batch to hold temporarly any message until
            // the connection is fully established.
            _batch = 0;
            _startBatch();

            // Save the original properties provided by the user
            // Deep copy to avoid the user to be able to change them later
            _handshakeProps = $.extend(true, {}, handshakeProps);

            var bayeuxMessage = {
                version: '1.0',
                minimumVersion: '0.9',
                channel: '/meta/handshake',
                supportedConnectionTypes: _xd ? ['callback-polling'] : ['long-polling', 'callback-polling']
            };
            // Do not allow the user to mess with the required properties,
            // so merge first the user properties and *then* the bayeux message
            var message = $.extend({}, handshakeProps, bayeuxMessage);

            // We started a batch to hold the application messages,
            // so here we must bypass it and deliver immediately.
            _setStatus('handshaking');
            _deliver([message], false);
        }

        function _findTransport(handshakeResponse)
        {
            var transportTypes = handshakeResponse.supportedConnectionTypes;
            if (_xd)
            {
                // If we are cross domain, check if the server supports it, that's the only option
                if ($.inArray('callback-polling', transportTypes) >= 0) return _transport;
            }
            else
            {
                // Check if we can keep long-polling
                if ($.inArray('long-polling', transportTypes) >= 0) return _transport;

                // The server does not support long-polling
                if ($.inArray('callback-polling', transportTypes) >= 0) return newCallbackPollingTransport();
            }
            return null;
        }

        function _delayedHandshake()
        {
            _setStatus('handshaking');
            _delayedSend(function()
            {
                _handshake(_handshakeProps);
            });
        }

        function _delayedConnect()
        {
            _setStatus('connecting');
            _delayedSend(function()
            {
                _connect();
            });
        }

        function _delayedSend(operation)
        {
            _cancelDelayedSend();
            var delay = _backoff;
            _debug("Delayed send: backoff {}, interval {}", _backoff, _advice.interval);
            if (_advice.interval && _advice.interval > 0)
                delay += _advice.interval;
            _scheduledSend = _setTimeout(operation, delay);
        }

        function _cancelDelayedSend()
        {
            if (_scheduledSend !== null) clearTimeout(_scheduledSend);
            _scheduledSend = null;
        }

        function _setTimeout(funktion, delay)
        {
            return setTimeout(function()
            {
                try
                {
                    funktion();
                }
                catch (x)
                {
                    _debug('Exception during scheduled execution of function \'{}\': {}', funktion.name, x);
                }
            }, delay);
        }

        /**
         * Sends the connect message
         */
        function _connect()
        {
            _debug('Starting connect');
            var message = {
                channel: '/meta/connect',
                connectionType: _transport.getType()
            };
            _setStatus('connecting');
            _deliver([message], true);
            _setStatus('connected');
        }

        function _send(message)
        {
            if (_batch > 0)
                _messageQueue.push(message);
            else
                _deliver([message], false);
        }

        /**
         * Delivers the messages to the comet server
         * @param messages the array of messages to send
         */
        function _deliver(messages, comet)
        {
            // We must be sure that the messages have a clientId.
            // This is not guaranteed since the handshake may take time to return
            // (and hence the clientId is not known yet) and the application
            // may create other messages.
            $.each(messages, function(index, message)
            {
                message['id'] = _nextMessageId();
                if (_clientId) message['clientId'] = _clientId;
                messages[index] = _applyOutgoingExtensions(message);
            });

            var self = this;
            var envelope = {
                url: _url,
                messages: messages,
                onSuccess: function(request, response)
                {
                    try
                    {
                        _handleSuccess.call(self, request, response, comet);
                    }
                    catch (x)
                    {
                        _debug('Exception during execution of success callback: {}', x);
                    }
                },
                onFailure: function(request, reason, exception)
                {
                    try
                    {
                        _handleFailure.call(self, request, messages, reason, exception, comet);
                    }
                    catch (x)
                    {
                        _debug('Exception during execution of failure callback: {}', x);
                    }
                }
            };
            _debug('Sending request to {}, message(s): {}', envelope.url, JSON.stringify(envelope.messages));
            _transport.send(envelope, comet);
        }

        function _applyIncomingExtensions(message)
        {
            $.each(_extensions, function(index, extension)
            {
                var callback = extension.extension.incoming;
                if (callback && typeof callback === 'function')
                {
                    _debug('Calling incoming extension \'{}\', callback \'{}\'', extension.name, callback.name);
                    message = _applyExtension(extension.name, callback, message) || message;
                }
            });
            return message;
        }

        function _applyOutgoingExtensions(message)
        {
            $.each(_extensions, function(index, extension)
            {
                var callback = extension.extension.outgoing;
                if (callback && typeof callback === 'function')
                {
                    _debug('Calling outgoing extension \'{}\', callback \'{}\'', extension.name, callback.name);
                    message = _applyExtension(extension.name, callback, message) || message;
                }
            });
            return message;
        }

        function _applyExtension(name, callback, message)
        {
            try
            {
                return callback(message);
            }
            catch (x)
            {
                _debug('Exception during execution of extension \'{}\': {}', name, x);
                return message;
            }
        }

        function _handleSuccess(request, response, comet)
        {
            var messages = _convertToMessages(response);
            _debug('Received response {}', JSON.stringify(messages));
            var success = true;
            $.each(messages, function(index, message)
            {
                message = _applyIncomingExtensions(message);
                if (message.advice) _advice = message.advice;

                // Plain user messages do not have the successful property
                var successful = message.successful;
                success = success && (successful === undefined || successful);

                var channel = message.channel;
                switch (channel)
                {
                    case '/meta/handshake':
                        _handshakeSuccess(message);
                        break;
                    case '/meta/connect':
                        _connectSuccess(message);
                        break;
                    case '/meta/disconnect':
                        _disconnectSuccess(message);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?