有没有一种方法可以“监听”数据库事件并实时更新页面?

39
我正在寻找一种创建简单HTML表格的方法,该表格可以在数据库更改事件(特别是添加新记录)时进行实时更新。
换句话说,可以将其视为执行仪表板。如果进行销售并在数据库中添加了新行(在我这种情况下是MySQL),则Web页面应使用新行“刷新”表格。
我已经看到有关使用EVENT GATEWAY的一些信息,但所有示例都使用Coldfusion作为“推动者”,而不是“使用者”。我希望Coldfusion可以同时更新/推送到网关并消耗响应。
如果可以使用AJAX和CF的组合来完成,请告诉我!
我真正想知道的是如何开始进行实时更新。
谢谢!
<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>

Coldfusion:


(该段落为标题,无需翻译)
<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>

1
明显的解决方案听起来像是一个MySQL触发器,但这可能还需要一个用户自定义函数才能调用Web服务。这可能有些过度。如果您可以访问创建、更新和删除数据库调用的代码,那么您可以在那个点简单地添加一个额外的调用,以便通知其他系统的更改。如果是这种情况,请告诉我,我也会提交一个答案。 - leggetter
@leggetter,是的,情况就是这样。基本上,我有一个Web服务来更新数据库,它也可以充当通知器。我面临的问题是如何通知/响应通知? - AngeloS
好的,我已经提交了一个答案,解释了如何触发推送通知事件并使用实时推送解决方案。触发器可能很棘手,并不总是最简单的解决方案。 - leggetter
8个回答

8
这不是太难。简单的方法是通过 .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);

更新--五年后,2016年2月: 今天比2011年更容易实现。新的JavaScript框架,如Backbone.js可以直接连接到数据库,并在数据更改、更新或删除时触发UI元素(包括表格)的更改...这是这些框架的主要优点之一。此外,UI可以通过套接字连接实时更新到Web服务,然后可以捕获并采取行动。虽然这里描述的技术仍然有效,但今天有更多“实时”做事情的方法。


我喜欢Data Tables的方法。有没有办法设置AJAX来“监听”服务器端事件?我编写的插入记录的代码也可以作为通知器,我只需要知道如何通知和如何监听。那是一个AJAX函数还是服务器端函数? - AngeloS
我认为我会在setInterval循环中运行一个Ajax查询,这基本上只是javascript的一种方式,每隔X段时间触发一个函数。 Ajax将分页Cold Fusion,Cold Fusion将访问数据库并返回结果的JSON字符串。 对我来说,最容易理解的AJAX是Jquery的.ajax。 因此,构建一个执行ajax调用的函数,在成功时设置结果,并将所有内容封装在setInterval中。 很简单... - bpeterson76
这非常有道理。谢谢! 依您之见,由于我们每分钟对每个用户都会多次访问我的 DB/CF 服务,这是否是可扩展的解决方案? - AngeloS
@angelo,这取决于你的情况。数据库大小、查询复杂度、索引、连接和服务器特定性都会影响结果。当我尝试这样的事情时,我会加入调试代码来报告查询开始时间、结束时间等,然后尝试各种方法,直到获得最佳结果。 - bpeterson76
知道了,最有可能采用这个解决方案,只是在测试它的工作效果。同时,你在 ('#selector') 前面漏写了一个 "$" 符号。 - AngeloS

7
您可以使用HTML5中的SSE(服务器发送事件)功能。
Server-Sent Events(SSE)是一种标准,描述了服务器如何在建立初始客户端连接后向客户端启动数据传输。它们通常用于向浏览器客户端发送消息更新或连续数据流,并通过名为EventSource的JavaScript API设计来增强本机、跨浏览器的流式处理,通过该API,客户端请求特定的URL以接收事件流。
这里是一个简单的示例。

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


1
同意。这是官方规范:http://www.w3.org/TR/eventsource/ 另一个例子:https://developer.mozilla.org/en-US/docs/Server-sent_events/Using_server-sent_events - user2683246

6
在MS SQL中,您可以将触发器附加到表的插入/删除/更新事件,以触发存储过程来调用Web服务。如果Web服务是基于CF的,则可以通过事件网关调用消息服务。任何监听网关的内容都可以被通知刷新其内容。话虽如此,您需要查看MySQL是否支持触发器和通过存储过程访问Web服务。您还需要在Web应用程序中拥有某种组件来监听消息网关。在Adobe Flex应用程序中很容易实现,但我不确定JavaScript中是否有可比较的组件。
虽然这个答案并没有直接回答您的问题,但也许它会给您一些使用数据库触发器和CF消息网关解决问题的思路。
M. McConnell

是的,我看了很多Flex的例子,这也是我首先提出这个问题的原因,但我喜欢你关于触发调用Web服务的SP的想法。不过,我仍会继续寻找合适的消息服务,因为这是目前最困扰我的问题。 - AngeloS

3
请看AJAX长轮询。起点是Comet。 Comet

2
谢谢你的回复。我对长轮询进行了一些研究,但是在我看到的示例中(比如这个 SO link 问题),似乎说它由于多个连接等原因不太可扩展。你是否有一个可扩展的示例? - AngeloS

3

使用“当前”技术,我认为使用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


1
这是我最喜欢的想法,但我担心的是我的用户使用不支持HTML5的旧浏览器。这是否应该是一个合理的担忧? - AngeloS
是的,这是一个合理的担忧。然而,ColdFusion 10的新CFWEBSOCKET标签可以在支持HTML5的浏览器上启用HTML5功能,否则它会退回到Flash小部件来提供推送功能。如果没有CF10,你将不得不编写自己的备用方案或使用类似于这样的东西:http://code.google.com/p/jquery-graceful-websocket/。 - Adrian J. Moreno

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

有了..你有没有实时更新所需代码的通知示例?这是通过AJAX还是直接通过ColdFusion完成的? - AngeloS
@AngeloS 我建议使用Ajax。我不是ColdFusion程序员,所以无法给你提供示例... 唉。然而,这个想法很简单:通过JavaScript定期发出Ajax请求到某个服务,该服务会对数据库进行检查。一旦发现有记录被添加,就相应地采取行动。 - Matthew Cox
这是不正确的。例如在PostgreSQL中,您可以使用触发器通过通知API发布事件。我几天前开始了一个使用这个想法的项目 https://github.com/cameron-martin/live_query - Cameron Martin

0
浏览器可以通过与Jabber/XMPP服务器的BOSH连接接收实时更新。所有细节都可以在这本书 http://professionalxmpp.com/ 中找到,我强烈推荐阅读。如果你能在数据库记录添加后以某种方式发送XMPP消息,那么构建所需的仪表板就相对容易了。你需要strophe.js、Jabber/XMPP服务器(如ejabberd)、用于代理http-bind请求的http服务器。所有细节都可以在这本书中找到,我坚信它是必读的,一定能帮助你解决问题。

0
我会实现通知的方式是在数据库更新成功提交后,我会发布一个事件,告诉任何监听系统或甚至网页该更改已发生。我在最近的博客文章中详细介绍了使用电子商务解决方案完成此操作的一种方法recent blog post。该博客文章展示了如何在ASP.NET中触发事件,但由于最终触发器是通过REST API调用执行的,因此可以轻松地在任何其他语言中完成相同的操作。
这篇博客文章中的解决方案使用Pusher,但您也可以安装自己的实时服务器或使用消息队列在应用程序和实时服务器之间进行通信,然后将通知推送到网页或客户端应用程序。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接