添加到WebSocket.onmessage()中,就像jQuery添加到事件中一样



我正在写一个单页的ws-++网站,我想让我的代码先按"page"分组(我想我需要一个新词,因为它永远不会回发),然后按节分组,然后按概念分组。

我想在我的代码中拆分WebSocket.onmessage,就像$('#someElement')可以不断地添加click(function(){})这样的事件一样

这可以用WebSocket.onmessage(function(){})完成吗?如果是,如何?


正如一些jQuery程序员很高兴地知道的那样,一个事件最初可以设置,然后在js的多个位置添加。这是我最喜欢js的地方,"只要它有序,就把它放在任何地方"的能力。这至少让代码组织对我来说容易多了。

对于WebSockets,实际上,到目前为止,我的操作客户端是使用WebSocket.onmessage()处理程序,因为WebSocket.send()可以在任何地方使用,实际上只是将js数据端口到服务器。

onmessage()现在拥有我的页面,因为其中的任何内容都会启动大多数主要操作,例如在收到"登录成功"类型的消息后,将登录屏幕淡出到第一个内容屏幕。

根据我对js的有限理解,onmessage()处理程序必须全部设置在一个地方。在我更改了它周围的js之后,继续向后滚动/切换到另一个文件来对它进行更改是一件很痛苦的事情。

如何在js的多个位置添加到WebSocket.onmessage()处理程序?

回答您的最后一个问题;

如何在js的多个位置添加onmessage处理程序?

您可以定义自己的个人(全局)事件处理程序,在其中您可以接受任意数量的处理程序函数。这里有一个例子:

window.bind: function(name, func, context) {
    if (typeof this.eventHandlers[name] == "undefined") {
        this.eventHandlers[name] = [func];
        this.eventContexts[name] = [context];
    }
    else {
        var found = false;
        for (var index in this.eventHandlers[name]) {
            if (this.eventHandlers[name][index] == func && this.eventContexts[name][index] == context) {
                found = true;
                break;
            }
        }
        if (!found) {
            this.eventHandlers[name].push(func);
            this.eventContexts[name].push(context);
        }
    }
}
window.trigger: function(name, args) {
    if (typeof this.eventHandlers[name] != "undefined") {
        for (var index in this.eventHandlers[name]) {
            var obj = this.eventContexts[name][index];
            this.eventHandlers[name][index].apply(obj, [args]);
        }
    }
}
// === Usage ===
//First you will bind an event handler some where in your code (it could be anywhere since `.bind` method is global).
window.bind("on new email", function(params) { ... });
//Then you need to trigger "on new email" in `onmessage` once appropriate events happen.
WebSocket.onmessage(function(data) {
    //Work on data and trigger based on that
    window.trigger("on new email", { subject: data.subject, email: data.email });
})

这段代码是我以前参与的一个开源项目的一部分。它提供事件名称,并允许您为处理程序设置上下文(用于方法而非函数)。然后,您可以在套接字的onmessage处理程序中调用触发器。我希望这就是你想要的。

您可以创建一个包装器,该包装器将处理自身上的WS事件。参见此示例CoffeeScript:

class WebSocketConnection
  constructor: (@url) ->
    @ws           = new WebSocket(@url)
    @ws.onmessage = @onMessage
    @callbacks    = []
  addCallback: (callback) ->
    @callbacks.push callback
  onMessage: (event) =>
    for callback in @callbacks
      callback.call @, event
# and now use it
conn = new WebSocketConnection(url)
conn.addCallback (event) =>
  console.log event

您可以使用addEventListener:

socket.addEventListener('message', function (event) {
    console.log('Message from server ', event.data);
});

我构建了一个CoffeeScript类来解决这个问题。它与@Valent的类似,但功能更全面,所以我想我会分享它。它为web套接字事件提供"on""off""clear"方法,还为"send""close"提供转发功能,这样你几乎不必直接触摸套接字。如果您确实需要访问实际的WebSocket对象,您可以通过superWebSocket.ws访问。

edit:我添加了一个getConnection静态方法来生成依赖url的singleton。这样,每个url只有一个连接,如果你试图创建第二个连接,它只会给你现有的连接。它还可以防止任何人直接调用构造函数。

edit:我使用JSON通过套接字进行通信。我添加了一些代码,这些代码将对传递到send的任何非字符串运行JSON.stringify,还将尝试对通过处理程序接收的任何消息运行JSON.parse

superSockets = {}
class SuperWebSocket
    @getConnection: (url)->
        superSockets[url] ?= new SuperWebSocket url
        superSockets[url]
    constructor: (url)->
        if arguments.callee.caller != SuperWebSocket.getConnection
            throw new Error "Calling the SuperWebSocket constructor directly is not allowed. Use SuperWebSocket.getConnection(url)"
        @ws = new WebSocket url
        events = ['open', 'close', 'message', 'error']
        @handlers = {}
        events.forEach (event)=>
            @handlers[event] = []
            @ws["on#{event}"] = (message)=>
                if message?
                    try
                        message = JSON.parse message.data
                    catch error
                for handler in @handlers[event]
                    handler message
                null
    on: (event, handler)=>
        @handlers[event] ?= []
        @handlers[event].push handler
        this
    off: (event, handler)=>
        handlerIndex = @handlers[event].indexOf handler
        if handlerIndex != -1
            @handlers[event].splice handlerIndex, 1
        this
    clear: (event)=>
        @handlers[event] = []
        this
    send: (message)=>
        if typeof(message) != 'string'
            message = JSON.stringify message
        @ws.send message
    close: => @ws.close()

相关内容

  • 没有找到相关文章

最新更新