【问题标题】:Is there a way to 'listen' for a database event and update a page in real time?有没有办法“监听”数据库事件并实时更新页面?
【发布时间】:2011-09-22 05:56:31
【问题描述】:

我正在寻找一种方法来创建一个简单的 HTML 表格,该表格可以在数据库更改事件时实时更新;特别是添加了一条新记录。

换句话说,把它想象成一个执行仪表板。如果进行了销售并且在数据库中添加了新行(在我的例子中是 MySQL),那么网页应该用新行“刷新”表格。

我已经看到了一些关于使用EVENT GATEWAY 的新信息,但所有示例都使用 Coldfusion 作为“推动者”而不是“消费者”。我想让 Coldfusion 将事件更新/推送到网关并使用响应。

如果这可以使用 AJAX 和 CF 的组合来完成,请告诉我!

我真的只是想了解从哪里开始实时更新。

提前谢谢你!!

编辑/所选答案的解释:

我最终选择了@bpeterson76 的答案,因为目前它最容易小规模实施。我真的很喜欢他的 Datatables 建议,这就是我用来接近实时更新的内容。

随着我的网站变大(希望如此),我不确定这是否是一个可扩展的解决方案,因为每个用户都会点击“监听器”页面,然后查询我的数据库。我的查询比较简单,但我还是担心以后的性能。

但在我看来,随着 HTML5 开始成为 Web 标准,@iKnowKungFoo 建议的 Web Sockets 方法很可能是最好的方法。 Comet 长轮询也是一个好主意,但实现起来有点麻烦/似乎还有一些扩展问题。

所以,让我们希望网络用户开始采用支持 HTML5 的更现代的浏览器,因为 Web Sockets 是一种接近实时的相对简单且可扩展的方式。

如果您觉得我做出了错误的决定,请发表评论。

最后,这里有一些源代码:

Javascript:

注意,这是一个非常简单的实现。它只是查看当前数据表中的记录数是否已更改,如果更改则更新表并发出警报。生产代码更长,涉及更多。这只是展示了一种接近实时更新的简单方法。

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.js"></script>
<script type="text/javascript" charset="utf-8">

var originalNumberOfRecsInDatatable = 0;
var oTable;

var setChecker = setInterval(checkIfNewRecordHasBeenAdded,5000); //5 second intervals

function checkIfNewRecordHasBeenAdded() {

        //json object to post to CFM page
        var postData = {
        numberOfRecords:  originalNumberOfRecsInDatatable 
        };

        var ajaxResponse = $.ajax({
        type: "post",
        url: "./tabs/checkIfNewItemIsAvailable.cfm",
        contentType: "application/json",
        data: JSON.stringify( postData )
        })

        // When the response comes back, if update is available
        //then re-draw the datatable and throw an alert to the user
        ajaxResponse.then(
        function( apiResponse ){

         var obj = jQuery.parseJSON(apiResponse);

         if (obj.isUpdateAvail == "Yes")
         {              
            oTable = $('#MY_DATATABLE_ID').dataTable();
            oTable.fnDraw(false);

            originalNumberOfRecsInDatatable = obj.recordcount;

            alert('A new line has been added!');
         }

        }
        );

    }
</script>

冷融合:

<cfset requestBody = toString( getHttpRequestData().content ) />

<!--- Double-check to make sure it's a JSON value. --->
<cfif isJSON( requestBody )>

<cfset deserializedResult = deserializeJSON( requestBody )>

<cfset numberOFRecords = #deserializedResult.originalNumberOfRecsInDatatable#>


<cfquery  name="qCount" datasource="#Application.DBdsn#" username="#Application.DBusername#" password="#Application.DBpw#">
    SELECT COUNT(ID) as total
    FROM myTable
</cfquery>

<cfif #qCount.total# neq #variables.originalNumberOfRecsInDatatable#>
    {"isUpdateAvail": "Yes", "recordcount": <cfoutput>#qCount.total#</cfoutput>}
<cfelse>
    {"isUpdateAvail": "No"}
</cfif>


</cfif>

【问题讨论】:

  • 显而易见的解决方案听起来像MySQL Trigger,但可能还需要User Defined Function 才能调用Web 服务。这可能是过度杀戮。您是否有权访问进行 CREATE、UPDATE 和 DELETE 数据库调用的代码?如果是这样,您可以在该点简单地添加和额外的调用以将更改通知到其他系统。如果是这种情况,请告诉我,我也会提交答案。
  • @leggetter,是的,就是这样。基本上,我有一个更新数据库的 Web 服务,它也可以充当通知程序。我面临的问题是如何通知/响应通知?
  • 好的,我已经提交了一个答案,解释了我将如何触发推送通知事件并使用实时推送解决方案。触发器可能很棘手,并不总是最简单的解决方案。

标签: mysql ajax coldfusion real-time


【解决方案1】:

这并不难。简单的方法是通过 .append 添加:

$( '#table > tbody:last').append('<tr id="id"><td>stuff</td></tr>');

实时添加元素是不可能的。您必须运行一个循环更新的 Ajax 查询以“捕获”更改。所以,不是完全实时的,但非常非常接近它。您的用户真的不会注意到差异,尽管您的服务器的负载可能会。

但如果您要更多参与,我建议您查看DataTables。它为您提供了许多新功能,包括排序、分页、过滤、限制、搜索和 ajax 加载。从那里,您可以通过 ajax 添加元素并刷新表格视图,或者简单地通过其 API 追加。我已经在我的应用程序中使用 DataTables 有一段时间了,它们一直被认为是使海量数据可用的第一大功能。

--编辑--

因为不明显,要更新您调用的 DataTable,请将您的 Datatables 调用设置为一个变量:

var oTable = $('#selector').dataTable();

然后运行这个来进行更新:

  oTable.fnDraw(false);

更新 -- 5 年后,2016 年 2 月: 这在今天比 2011 年更有可能。新的 Javascript 框架(例如 Backbone.js)可以直接连接到数据库并触发 UI 元素的更改,包括更改、更新或删除数据的表格......这是其中之一这些框架的主要好处。此外,可以通过与 Web 服务的套接字连接向 UI 提供实时更新,然后也可以捕获并采取行动。虽然这里描述的技术仍然有效,但今天还有更多“活”的做事方式。

【讨论】:

  • 我喜欢数据表方法。有没有办法设置 AJAX 来“监听”服务器端事件?我编写的插入记录的代码也可以用作通知器,我只需要知道如何通知和如何收听。那是 AJAX 函数还是服务器端函数?
  • 我想我会在 setInterval 循环中运行 Ajax 查询,这基本上只是 javascript 每 X 时间段触发一个函数的方式。 Ajax 将分页 Cold Fusion,这将访问数据库并返回 JSON 字符串结果。对我来说,最容易理解的 AJAX 是 Jquery 的 .ajax。因此,构建一个执行 ajax 调用的函数,成功设置您的结果,并用 setInterval 将所有内容括起来。简单的Peasy....
  • 这完全有道理。谢谢! .. 在您看来,这是否是一个可扩展的解决方案,因为我们每个用户每分钟会多次访问我的数据库/CF 服务?
  • @angelo,这取决于您的情况。数据库大小、查询复杂性、索引、连接和服务器细节都会影响结果。当我尝试这样的事情时,我输入了报告时间开始、时间结束等的调试代码以进行查询,然后尝试直到获得最佳结果。
  • Gotcha.. 很可能会采用这个解决方案,只是测试它是如何工作的。此外,您在 ('#selector') 前面缺少一个“$”
【解决方案2】:

您可以使用 HTML5 中的 SSE(服务器发送事件)功能。

服务器发送事件 (SSE) 是一种标准,描述了一旦建立初始客户端连接,服务器如何向客户端发起数据传输。它们通常用于向浏览器客户端发送消息更新或连续数据流,旨在通过称为 EventSource 的 JavaScript API 增强本地跨浏览器流式传输,客户端通过该 API 请求特定 URL 以接收事件流。

这是一个简单的例子

http://www.w3schools.com/html/html5_serversentevents.asp

【讨论】:

【解决方案3】:

我实现通知的方式是在数据库更新成功提交后,我会发布一个事件,告诉任何监听系统甚至网页发生了更改。我在recent blog post 中详细介绍了一种使用电子商务解决方案的方法。博客文章展示了如何在 ASP.NET 中触发事件,但同样的事情可以用任何其他语言轻松完成,因为最终触发是通过 REST API 调用执行的。

这篇博文中的解决方案使用Pusher,但没有理由不能安装自己的实时服务器或使用消息队列在您的应用程序和实时服务器之间进行通信,然后推送通知到网页或客户端应用程序。

【讨论】:

    【解决方案4】:

    浏览器可以通过 BOSH 连接到 Jabber/XMPP 服务器接收实时更新。所有的点点滴滴都可以在本书http://professionalxmpp.com/ 中找到,我强烈推荐。如果您可以在数据库中添加记录时发送 XMPP 消息,那么构建您想要的仪表板相对容易。您需要 strophe.js、Jabber/XMPP 服务器(例如 ejabberd)、用于代理 http-bind 请求的 http 服务器。所有细节都可以在书中找到。必读,我坚信可以解决您的问题。

    【讨论】:

      【解决方案5】:

      查看 AJAX 长轮询。 起点Comet

      【讨论】:

      • 感谢您的回复。我对长轮询进行了一些研究,但是在我看到的示例中(例如这个 SO link 问题)似乎说由于多个连接等原因它的可扩展性不高。您碰巧有一个可扩展的示例吗?跨度>
      【解决方案6】:

      对于“当前”技术,我认为使用 Ajax 进行长轮询是您唯一的选择。但是,如果您可以使用 HTML5,您应该看看 WebSockets,它为您提供了您想要的功能。

      http://net.tutsplus.com/tutorials/javascript-ajax/start-using-html5-websockets-today/

      WebSockets 是一种通过一个 (TCP) 套接字进行双向通信的技术,是一种 PUSH 技术。目前,它仍在被 W3C 标准化;但是,最新版本的 Chrome 和 Safari 支持 WebSockets。

      http://html5demos.com/web-socket

      【讨论】:

      • 这是我最喜欢的想法,但我担心的是我的用户使用不支持 HTML5 的旧浏览器。这应该是一个有效的担忧吗?
      • 是的,这是一个值得关注的问题。然而,ColdFusion 10 的新 CFWEBSOCKET 标签在支持 HTML5 的浏览器上启用了 HTML5 功能,否则它会退回到 Flash 小部件来提供推送功能。如果没有 CF10,您将不得不编写自己的后备或使用类似这样的内容:code.google.com/p/jquery-graceful-websocket
      【解决方案7】:

      MS SQL 中,您可以将触发器附加到表插入/删除/更新事件,该事件可以触发存储过程来调用 Web 服务。如果 Web 服务是基于 CF 的,那么您可以反过来使用事件网关调用消息传递服务。任何监听网关的东西都可以被通知刷新其内容。也就是说,您必须查看 MySQL 是否支持触发器和通过存储过程访问 Web 服务。您还必须在 Web 应用程序中有某种组件来监听消息传递网关。在 Adob​​e Flex 应用程序中很容易做到这一点,但我不确定 JavaScript 中是否有可访问的类似组件。

      虽然这个答案不能直接解决您的问题,但也许它会给您一些关于如何使用 db 触发器和 CF 消息传递网关解决问题的想法。

      M.麦康奈尔

      【讨论】:

      • 是的,我看到了一堆 Flex 示例,这让我首先想到了这个问题,但我喜欢你关于触发调用 Web 服务的 SP 的想法。我将继续寻找合适的消息服务,因为这是目前最让我烦恼的。
      【解决方案8】:

      不,您不能让任何数据库代码执行服务器端代码。但是您可以编写一个服务来定期轮询数据库以查看是否添加了新记录,然后通知您拥有的需要伪实时更新的代码。

      【讨论】:

      • Gotcha.. 你有什么例子说明如何通知需要实时更新的代码吗?这是通过 AJAX 完成还是直接通过 ColdFusion 完成?
      • @AngeloS 我建议使用 Ajax。我不是 ColdFusion 程序员,所以我不能给你举例……嗯。但是,这个想法很简单:通过 javascript 向某些服务发出定期 ajax 请求,以检查数据库。一旦发现已添加记录,请采取相应措施。
      • 这是不正确的。例如在 postgres 中,您可以使用触发器通过通知 API 发布事件。几天前我用这个想法开始了一个项目github.com/cameron-martin/live_query
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-23
      • 2011-12-21
      • 1970-01-01
      • 1970-01-01
      • 2019-06-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多