Websocket 如何将数据推送到基于SQL语句的浏览器?

Websocket 如何将数据推送到基于SQL语句的浏览器?,websocket,push-notification,long-polling,polling,Websocket,Push Notification,Long Polling,Polling,我知道在这个话题上有很多线索,但似乎确实回答了我想要的答案。我以前从来没有做过任何推送技术,所以这里的一些指导非常感谢。我知道当某些事情发生变化时,会触发推送到任何正在侦听的浏览器,但我认为这并不完全符合我正在尝试的场景 我们正在重建用户的web应用程序,以便他们跟踪发货。我们将允许用户建立自己的搜索,以匹配他们的工作方式。例如,有些人会查找计划今天交付的任何装运,而有些人会查找今天要提货的装运,还有一些人会查找需要计划提货的装运。因此,当他们打开应用程序时,我可以为他们计算他们今天需要完成的每

我知道在这个话题上有很多线索,但似乎确实回答了我想要的答案。我以前从来没有做过任何推送技术,所以这里的一些指导非常感谢。我知道当某些事情发生变化时,会触发推送到任何正在侦听的浏览器,但我认为这并不完全符合我正在尝试的场景

我们正在重建用户的web应用程序,以便他们跟踪发货。我们将允许用户建立自己的搜索,以匹配他们的工作方式。例如,有些人会查找计划今天交付的任何装运,而有些人会查找今天要提货的装运,还有一些人会查找需要计划提货的装运。因此,当他们打开应用程序时,我可以为他们计算他们今天需要完成的每个工作任务。现在我想要的是,计数将根据重新运行的SQL而改变。但是我不希望用户必须刷新页面才能看到新的计数

如何运行此SQL并将当前计数推送到使用此SQL的任何浏览器。自动重新运行此SQL的机制是什么?请记住,我将有50个或更多这些独特的SQL需要执行和计数


谢谢你的指导

我认为这完全属于AJAX的角色。AJAX将允许您向服务器发出GET和POST请求,服务器将处理查询并将结果返回给JS函数。冒着jQuery传播的风险,API使这类事情变得非常简单和标准,您几乎可以拥有任何想要激活它的事件

这有几个问题,即客户端输入和SQL注入。如果您通过POST请求发送任何输入,您必须非常小心地清理所有内容。使用预先准备好的语句,不要执行查询字符串concatation+执行,并且通常假定用户将尝试发送您不希望发送的文本。为将成功确认的输入提供一些服务器端边界(例如,如果选项为“左”或“右”,并且它们给出了“底部”,则默认为“底部”或将其删除)

  • 客户端激活请求(定时或事件)
  • JS对服务器进行AJAX调用(可选参数)
  • 服务器验证任何输入并处理查询
  • 服务器返回结果
  • JS使用结果修改DOM

  • AJAX拉取是一种解决方案,尽管其他解决方案可能更适合并为您节省资源*

    例如,拥有一个持久的Websocket连接将有助于最大限度地降低建立新连接和重复请求(大部分是冗余的)的成本

    因此,您的服务器应该具有较低的工作负载,并且您的应用程序将需要较少的带宽(如果这些对您很重要的话)

    即使使用Websocket连接只是告诉客户机何时发送AJAX请求,有时也可以节省资源

    这里有一个快速的Websocket推送演示 您可以使用许多不同的Websocket解决方案。我用编写了一个快速演示,因为它非常容易实现,但还有其他方法可以实现

    Plezi框架是一个Ruby框架,它运行自己的HTTP和Websocket服务器,独立于Rack

    示例代码包括用于模型的控制器(DemoController)、用于根索引页的控制器(DemoIndex)和用于Websocket连接的控制器(MyWSController)

    示例代码看起来更长,因为它都在一个脚本中-甚至用作客户端的HTML页面。。。但它确实很容易阅读

    搜索要求从客户端发送到web服务器(搜索要求模型的对象ID介于0和50之间)

    每次创建(或更新)对象时,都会向所有连接的客户端发送警报,首先运行每个客户端的搜索,然后发送任何更新

    服务器休息的其余时间(除了每隔45秒左右ping一次,以保持websocket连接的活动状态)

    要查看演示,只需在IRB终端**内复制并粘贴以下代码,然后访问演示页面:

    require 'plezi'
    
    class MyWSController
        def on_open
            # save the user data / register them / whatever
            @searches = []
        end
        def on_message data
            # get data from the user
            data = JSON.parse data
            # sanitize data, create search parameters...
            raise "injection attempt: #{data}}" unless data['id'].match(/^\([\d]+\.\.[\d]+\)\z/)
            # save the search
            @searches << data
        end
        def _alert options
            # should check @searches here
            @searches.each do |search|
                if eval(search['id']).include? options[:info][:id]
                    # update
                    response << {event: 'alert'}.merge(options).to_json
                else
                    response << "A message wouldn't be sent for id = #{options[:info][:id]}.\nSaved resources."
                end
            end
        end
    end
    
    class DemoController
        def index
            "use POST to post data here"
        end
        # called when a new object is created using POST
        def save
            # ... save data posted in params ... then:
            _send_alert
        end
        # called when an existing object is posted using POST or UPDATE
        def update
            # ... update data posted in params ... then:
            _send_alert
        end
        def demo_update
            _send_alert message: 'info has been entered', info: params.update(id: rand(100), test: 'true')
            "        This is a demo for what happens when a model is updated.\n
            Please Have a look at the Websocket log for the message sent."
        end
        # sends an alert to 
        def _send_alert alert_data
            MyWSController.broadcast :_alert, alert_data
        end
    end
    
    class DemoIndex
        def index search = '(0..50)'
            response['content-type'] = 'text/html'
            <<-FINISH
    <html>
    <head>
    <style>
       html, body {height: 100%; width:100%;}
       #output {margin:0 5%; padding: 1em 2em; background-color:#ddd;}
       #output li {margin: 0.5em 0; color: #33f;}
    </style>
    </head><body>
    <h1> Welcome to your Websocket Push Client </h1>
    <p>Please open the following link in a <b>new</b> tab or browser, to simulate a model being updated: <a href='#{DemoController.url_for id: :demo_update, name: 'John Smith', email: 'john@gmail.com'}', target='_blank'>update simulation</a></p>
    <p>Remember to keep this window open to view how a simulated update effects this page.</p>
    <p>You can also open a new client (preferably in a new tab, window or browser) that will search only for id's between 50 and 100: <a href='#{DemoIndex.url_for :alt_search}'>alternative search</a></p>
    <p>Websocket messages recieved from the server should appeare below:</p>
    <ul id='output'>
    </ul>
    <script>
    var search_1 = JSON.stringify({id: '#{search}'})
    output = document.getElementById("output");
    websocket = new WebSocket("#{request.base_url 'ws'}/ws"); 
    websocket.onmessage = function(e) { output.innerHTML += "<li>" + e.data + "</li>" }
    websocket.onopen = function(e) { websocket.send(search_1) }
    </script>
    </body></html>
    FINISH
        end
        def alt_search
            index '(50..100)'
        end
    end
    
    listen
    
    route '/model', DemoController
    route '/ws', MyWSController
    route '/', DemoIndex
    
    exit
    
    需要“plezi”
    类MyWSController
    def on_打开
    #保存用户数据/注册用户/无论什么
    @搜索=[]
    结束
    def on_消息数据
    #从用户获取数据
    data=JSON.parse数据
    #清理数据,创建搜索参数。。。
    除非数据['id'].match(/^\([\d]+\.\.[\d]+\)\z/),否则引发“注入尝试:{data}}}”
    #保存搜索
    
    @那么,是否有一个运行ajax调用的计时器?如果它是一个计时器,那么在用户机器上使用内存不会有副作用吗?有多种方法可以让JS等待去做事情。对于在计时器上重复执行某项操作,我会使用,它需要执行一个函数,并在重复该函数之前等待一个以毫秒为单位的间隔。执行的函数是任意的,但在您的情况下,它将是一个进行AJAX调用的函数。它使用了一些内存,但不是很大的内存量,因为它的大部分操作只是检查间隔是否已过,这不是一个很大的操作,并且您提供给它的函数在此之前不会被调用。谢谢-我将围绕这一点来玩,看看会发生什么。谢谢你的指导,没问题。如果这回答了您的问题,您应该将其标记为答案,以便其他人知道它已完成。另外,我做了一些小的研究来确认setInterval实际上并没有占用太多内存。Chrome的时间轴模式显然有一个小怪癖,它报告占用的内存比实际占用的内存多,但事实上,如果你没有运行大量的实例,这是一件非常小的事情。