3

我正在编写一个单页ws++网站,我想先按“页面”分组我的代码(我认为我需要一个新词,因为它从不回发)然后按部分然后按概念等。

我想以与可以不断添加事件WebSocket.onmessage的方式相同的方式拆分我的代码。$('#someElement')click(function(){})

这可以做到WebSocket.onmessage(function(){})吗?如果是这样,怎么做?


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

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

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

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

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

4

4 回答 4

4

回答你的最后一个问题;

如何在 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 处理程序中调用 trigger 。我希望这就是你要找的。

于 2013-07-06T15:42:51.693 回答
3

您可以创建一个包装器来处理自身的 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
于 2013-07-06T15:51:25.853 回答
1

你可以这样做addEventListener

socket.addEventListener('message', function (event) {
    console.log('Message from server ', event.data);
});
于 2017-12-13T14:50:33.883 回答
0

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

编辑:我添加了一个getConnection静态方法来生成依赖于 url 的单例。这样,每个网址只有一个连接,如果您尝试创建第二个连接,它只会为您提供现有的连接。它还可以防止任何人直接调用构造函数。

编辑:我通过 JSON 中的套接字进行通信。我添加了一些代码,这些代码将JSON.stringify在传入的任何非字符串上运行,send并且还将尝试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()
于 2016-09-10T18:20:09.833 回答