有没有办法“听”对于数据库事件并实时更新页面?
我正在寻找一种方法来创建一个简单的 HTML 表,该表可以在数据库更改事件时实时更新;特别是添加了一条新记录。
换句话说,可以将其视为执行仪表板。如果进行了销售并且在数据库中添加了新行(在我的例子中是 MySQL),那么网页应该使用新行“刷新”表。
我已经看到了一些关于使用 EVENT GATEWAY
的新信息,但所有示例都使用 Coldfusion 作为“推动者”而不是“消费者”。我想让 Coldfusion 既更新/推送事件到网关,又使用响应。
如果可以使用 AJAX 和 CF 的组合来完成此操作,请告诉我!
我真的只是想了解从哪里开始实时更新。
先感谢您!!
编辑/所选答案的解释:
我最终选择了@bpeterson76的答案,因为目前它最容易小规模实施。我真的很喜欢他的数据表建议,这就是我用来近乎实时更新的建议。
随着我的网站变得越来越大(希望如此),我不确定这是否是一个可扩展的解决方案,因为每个用户都会点击“侦听器”页面,然后查询我的数据库。我的查询比较简单,但是我还是担心以后的性能。
但在我看来,随着 HTML5 开始成为 Web 标准,@iKnowKungFoo 建议的 Web Sockets 方法很可能是最好的方法。具有长轮询的 Comet 也是一个好主意,但实现起来有点麻烦/似乎也存在一些扩展问题。
因此,我们希望 Web 用户开始采用支持 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>
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>
I'm looking for a way to create a simple HTML table that can be updated in real-time upon a database change event; specifically a new record added.
In other words, think of it like an executive dashboard. If a sale is made and a new line is added in a database (MySQL in my case) then the web page should "refresh" the table with the new line.
I have seen some information on the new using EVENT GATEWAY
but all of the examples use Coldfusion as the "pusher" and not the "consumer". I would like to have Coldfusion both update / push an event to the gateway and also consume the response.
If this can be done using a combination of AJAX and CF please let me know!
I'm really just looking to understand where to get started with real-time updating.
Thank you in advance!!
EDIT / Explanation of selected answer:
I ended up going with @bpeterson76's answer because at the moment it was easiest to implement on a small scale. I really like his Datatables suggestion, and that's what I am using to update in close to real time.
As my site gets larger though (hopefully), I'm not sure if this will be a scalable solution as every user will be hitting a "listener" page and then subsequently querying my DB. My query is relatively simple, but I'm still worried about performance in the future.
In my opinion though, as HTML5 starts to become the web standard, the Web Sockets method suggested by @iKnowKungFoo is most likely the best approach. Comet with long polling is also a great idea, but it's a little cumbersome to implement / also seems to have some scaling issues.
So, let's hope web users start to adopt more modern browsers that support HTML5, because Web Sockets is a relatively easy and scalable way to get close to real time.
If you feel that I made the wrong decision please leave a comment.
Finally, here is some source code for it all:
Javascript:
note, this is a very simple implementation. It's only looking to see if the number of records in the current datatable has changed and if so update the table and throw an alert. The production code is much longer and more involved. This is just showing a simple way of getting a close to real-time update.
<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>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
这并不太难。简单的方法是通过 .append 添加:
实时添加元素并不完全可能。您必须运行一个循环更新的 Ajax 查询才能“捕获”更改。所以,不是完全实时,但非常非常接近实时。您的用户实际上不会注意到这种差异,尽管您的服务器负载可能会注意到。
但如果您想更多地参与其中,我建议您查看DataTables。它为您提供了很多新功能,包括排序、分页、过滤、限制、搜索和 ajax 加载。从那里,您可以通过 ajax 添加元素并刷新表视图,或者简单地通过其 API 附加。我在我的应用程序中使用 DataTables 一段时间了,它们一直被认为是使大量数据可用的第一大功能。
--编辑 --
因为它并不明显,要更新您调用的 DataTable,请将 Datatables 调用设置为变量:
然后运行此命令来执行更新:
UPDATE -- 5 年后,2016 年 2 月:
如今,这比 2011 年更有可能。新的 Javascript 框架(例如 Backbone.js)可以直接连接到数据库并触发 UI 元素的更改,包括数据更改、更新或删除的表......这是其中之一这些框架的主要好处。此外,UI 可以通过与 Web 服务的套接字连接获得实时更新,然后也可以捕获这些更新并采取行动。虽然这里描述的技术仍然有效,但今天有更多“实时”的做事方式。
This isn't too difficult. The simple way would be to add via .append:
Adding elements real-time isn't entirely possible. You'd have to run an Ajax query that updates in a loop to "catch" the change. So, not totally real-time, but very, very close to it. Your user really wouldn't notice the difference, though your server's load might.
But if you're going to get more involved, I'd suggest looking at DataTables. It gives you quite a few new features, including sorting, paging, filtering, limiting, searching, and ajax loading. From there, you could either add an element via ajax and refresh the table view, or simply append on via its API. I've been using DataTables in my app for some time now and they've been consistently cited as the number 1 feature that makes the immense amount of data usable.
--Edit --
Because it isn't obvious, to update the DataTable you call set your Datatables call to a variable:
Then run this to do the update:
UPDATE -- 5 years later, Feb 2016:
This is much more possible today than it was in 2011. New Javascript frameworks such as Backbone.js can connect directly to the database and trigger changes on UI elements including tables on change, update, or delete of data....it's one of these framework's primary benefits. Additionally, UI's can be fed real-time updates via socket connections to a web service, which can also then be caught and acted upon. While the technique described here still works, there are far more "live" ways of doing things today.
您可以使用 HTML5 中的 SSE(服务器发送事件)功能。
服务器发送事件 (SSE) 是一个标准,描述在建立初始客户端连接后服务器如何向客户端发起数据传输。它们通常用于向浏览器客户端发送消息更新或连续数据流,并旨在通过称为 EventSource 的 JavaScript API 增强本机跨浏览器流,客户端通过该 API 请求特定 URL 以接收事件流。
这是一个简单的例子
http://www.w3schools.com/html/html5_serversentevents.asp
You can use SSE (Server Sent Events) a feature in HTML5.
Server-Sent Events (SSE) is a standard describing how servers can initiate data transmission towards clients once an initial client connection has been established. They are commonly used to send message updates or continuous data streams to a browser client and designed to enhance native, cross-browser streaming through a JavaScript API called EventSource, through which a client requests a particular URL in order to receive an event stream.
heres a simple example
http://www.w3schools.com/html/html5_serversentevents.asp
在 MS SQL 中,您可以将触发器附加到表插入/删除/更新事件,该事件可以触发存储过程来调用 Web 服务。如果 Web 服务是基于 CF 的,则您可以依次使用事件网关调用消息传递服务。任何侦听网关的设备都可以收到通知以刷新其内容。也就是说,您必须查看 MySQL 是否支持触发器并通过存储过程访问 Web 服务。您还必须在您的网络应用程序中拥有某种组件来监听消息传递网关。在 Adobe Flex 应用程序中这很容易做到,但我不确定是否有可在 JavaScript 中访问的类似组件。
虽然这个答案并不能直接解决您的问题,但也许它会给您一些关于如何使用数据库触发器和 CF 消息传递网关解决问题的想法。
M·麦康奈尔
In MS SQL, you can attach a trigger to a table insert/delete/update event that can fire a stored proc to invoke a web service. If the web service is CF-based, you can, in turn, invoke a messaging service using event gateways. Anything listening to the gateway can be notified to refresh its contents. That said, you'd have to see if MySQL supports triggers and accessing web services via stored procedures. You'd also have to have some sort of component in your web app that's listening to the messaging gateway. It's easy to do in Adobe Flex applications, but I'm not sure if there are comparable components accessible in JavaScript.
While this answer does not come close to directly addressing your question, perhaps it will give you some ideas as to how to solve the problem using db triggers and CF messaging gateways.
M. McConnell
对于“当前”技术,我认为使用 Ajax 进行长轮询是您唯一的选择。但是,如果您可以使用 HTML5,您应该看看 WebSockets,它为您提供了您想要的功能。
http://net.tutsplus.com/tutorials/ javascript-ajax/start-using-html5-websockets-today/
http://html5demos.com/web-socket
With "current" technologies, I think long polling with Ajax is your only choice. However, if you can use HTML5, you should take a look at WebSockets which gives you the functionality you want.
http://net.tutsplus.com/tutorials/javascript-ajax/start-using-html5-websockets-today/
http://html5demos.com/web-socket
查看 AJAX 长轮询。
起始位置 Comet
Check out AJAX long polling.
Place to start Comet
不,您不能让任何数据库代码执行服务器端代码。但是您可以编写一个服务来定期轮询数据库以查看是否添加了新记录,然后通知您需要伪实时更新的代码。
No, you can't have any db code execute server side code. But you could write a service to poll the db periodically to see if a new record has been added then notify the code you have that needs pseudo real-time updates.
浏览器可以通过 BOSH 连接到 Jabber/XMPP 服务器接收实时更新。所有的细节都可以在我强烈推荐的http://professionalxmpp.com/这本书中找到。如果您可以在数据库中添加记录时发送 XMPP 消息,那么构建您想要的仪表板相对容易。您需要 strope.js、Jabber/XMPP 服务器(例如 ejabberd)、用于代理 http-bind 请求的 http 服务器。所有的细节都可以在书中找到。必读,我坚信它会解决您的问题。
The browser can receive real-time updates via BOSH connection to Jabber/XMPP server. All bits and pieces can be found in this book http://professionalxmpp.com/ which I highly recommend. If you can anyhow send XMPP message upon record addition in your DB, then it is relatively easy to build the dashboard you want. You need strophe.js, Jabber/XMPP server (e.g. ejabberd), http server for proxying http-bind requests. All the details can be found in the book. A must read which I strongly believe will solve your problem.
我实现通知的方法是在数据库更新成功提交后,我将发布一个事件,告诉任何侦听系统甚至网页已发生更改。我在 最近的博客文章。该博客文章展示了如何在 ASP.NET 中触发事件,但使用任何其他语言也可以轻松完成相同的操作,因为最终触发是通过 REST API 调用执行的。
本博文中的解决方案使用 Pusher,但您没有理由不能安装自己的实时服务器或使用消息队列用于您的应用程序和实时服务器之间的通信,然后实时服务器会将通知推送到网页或客户端应用程序。
The way I would achieve the notification is after the database update has been successfully committed I would publish an event that would tell any listening systems or even web pages that the change has occurred. I've detailed one way of doing this using an e-commerce solution in a recent blog post. The blog post shows how to trigger the event in ASP.NET but the same thing can easily be done in any other language since ultimately the trigger is performed via a REST API call.
The solution in this blog post uses Pusher but there's not reason why you couldn't install your own real-time server or use a Message Queue to communication between your app and the realtime server, which would then push the notification to the web page or client application.