0

我想为新闻门户建立一个评论系统。

我希望 jQuery AJAX 检测是否有人添加了评论数据,它会自动更新在 slideDown 动作中添加的评论。

我怎样才能做到这一点?谢谢。

(注意:我使用 ASP.NET 作为服务器)

在此处输入图像描述

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script>
        $(document).ready(function () {
            $.ajax({
                url: 'WebForm1.aspx',
                success: function (data) {
                    $("#Urunler").html(data);
                }
            });
        });
    </script>
    <style>
        li
        {
            width: 100px;
            height: 30px;
            background: yellow;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <div>


        <ul id="Urunler" runat="server">

        </ul>


    </div>
    </form>
</body>
</html>

这是后面的代码,

using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;

namespace WebApplication2
{
    public partial class WebForm1 : System.Web.UI.Page
    {

        SqlConnection cnn = new SqlConnection("Initial Catalog=Northwind;Data Source=localhost;Integrated Security=SSPI;");

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                cnn.Open();
                SqlCommand cmd = new SqlCommand("SELECT FirstName FROM Employees", cnn);
                SqlDataReader dr = cmd.ExecuteReader();
                if (dr.HasRows)
                {
                    while (dr.Read())
                    {
                        Urunler.InnerHtml += "<li>" + dr.GetString(0) + "</li>";
                    }
                }
                cnn.Close();
            }
        }
    }
}
4

6 回答 6

8

如果我猜对了,您正在寻找诸如 facebook/gmail 的实时通知之类的东西。

您可以通过实现几种架构来实现它:

  1. Ajax 池:每 N(假设 5)秒后向服务器发送一个 ajax 请求,服务器将为您提供最新的评论。这是最简单也是最重的方式。有了一点流量,即使没有任何事情发生,您也不会花费太多时间来处理大量不必要的请求,因为您会发出请求。
  2. Web Socket:您可以使用 socket.io 并打开一个套接字将更新中继到所有客户端。这是解决此问题的常用方法。一个也很漂亮。您可以使用答案来应对这种方法。
  3. Reverse Ajax/Comet:最后一个是最难的。Facebook 使用这种架构,因为他们正在处理一些高流量 (:p),我们可以假设这个架构具有扩展能力。您可以通过视频了解反向 ajax 或彗星方法。这个答案可以帮助您了解它。

更新: 这篇文章似乎提供了一些不同的技术来实现你的目标。它可能会有所帮助。

于 2013-11-16T12:43:57.617 回答
5

我会试一试!

这应该每五秒钟从服务器获取 LI,并将它们与任何现有评论进行比较,如果它们不同,则将新评论插入 DOM 并将它们向下滑动:

var comments = {
    get: function () {
        return $.ajax({ 
            url   : 'WebForm1.aspx',
            cache : false
        });
    },
    check: function (coll1, coll2, UL_ID) {
        var diff = [];
        $.each(coll2, function (_, li2) {
            var same = false;
            $.each(coll1, function (_, li1) {
                if ($(li1).text() == $(li2).text()) same = true;
            });
            if (!same) diff.push(li2);
        });
        this.output(diff, UL_ID);
    },
    poll: function (UL_ID) {
        var self = this;
        self.get().done(function (data) {
            self.check($(UL_ID).find('li'), $('<ul />').append(data).find('li'), UL_ID);
        });
    },
    output: function (elems, UL_ID) {
        $.each(elems, function (i, elem) {
            $(elem).hide().delay(i * 300).slideDown(350).appendTo($(UL_ID));
        });
    },
    init: function (UL, interval) {
        var self = this;
        setInterval(function () {
            self.poll(UL);
        }, interval);
        this.poll(UL);
    }
}

$(document).ready(function () {
    comments.init('#Urunler', 5000);
// ^^ starts plugin   ^^ ID     ^^ polling speed (5 seconds)
});

我强烈建议在数据库中为每条评论提供一个 UUID,然后使用它进行比较以查找新评论。
上面的代码现在只比较评论的内容,所以如果完全相同的评论被发布两次,可能会有问题。

似乎您的数据库输出的唯一内容是注释本身,没有唯一标识符,因此如果您要为 UUID 添加一行,则需要更改数据库结构,这在某种程度上超出了我认为的问题。

这是一个快速演示,其中数据库已替换为 localStorage

示范

于 2013-11-17T14:22:12.467 回答
2

您需要将已经加载的数据传递给服务器,服务器可以检查并返回尚未加载的数据。在这里我也推荐使用setTimeout代替setInterval。因为setInterval 总是会在一段时间后触发下一次调用,所以在函数内部你还使用了 ajax,这也是不合理的 => 当你的服务器负载很重且响应时间很慢时,这可能会变得混乱。在这个函数中,我们应该只在当前 ajax 完成后才设置下一个时间间隔。

<script>
        $(document).ready(function () {
            refreshComments(); //trigger the first call
        });

        function refreshComments(){
            var loadedIds = $("#Urunler li").map(function(){
                              return $(this).attr("employeeId");
                          }).get()
                          .join(",")); //get current loaded ids

            $.ajax({
                url: 'WebForm1.aspx?loaded='+loadedIds,
                success: function (data) {
                    if (data){ //append only when there is a newly added comment.
                       var element = $(data);
                       element.hide();
                       $("#Urunler").append(element);//use append instead of html because html will replace the old ones.
                       element.slideDown();
                       setTimeout(refreshComments,5000);
                    }
                }
            });

        }
</script>

需要更新服务器端代码以返回 id 并检查 id

using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;

namespace WebApplication2
{
    public partial class WebForm1 : System.Web.UI.Page
    {

        SqlConnection cnn = new SqlConnection("Initial Catalog=Northwind;Data Source=localhost;Integrated Security=SSPI;");

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                //Check for already loaded Ids, I assume that each record in your database has an Id
                string loadedIds = Request.QueryString["loaded"];
                string sql = "SELECT EmployeeId,FirstName FROM Employees";
                if (!string.IsNullOrEmpty(loadedIds)){
                    sql = "SELECT EmployeeId ,FirstName FROM Employees WHERE EmployeeId NOT IN (" 
                           + loadedIds +")";  
                }// You could query it using a safer method than string concatenation, here I just demonstrate the idea

                cnn.Open();

                SqlCommand cmd = new SqlCommand(sql, cnn);
                SqlDataReader dr = cmd.ExecuteReader();
                if (dr.HasRows)
                {
                    while (dr.Read())
                    {
                        //This should be a Literal Control, embed Id in the response.
                        Urunler.Text += string.Format("<li employeeId='{0}'>{1}</li>",dr.GetString(0),dr.GetString(1));
                    }
                }
                cnn.Close();
            }
        }
    }
}
于 2013-11-16T08:57:27.087 回答
0

你可以试试这个

        var lastSearchedDate =  new Date();
    var isBusy = false;

    function scrollEvent(e) {
        var body = document.body,
             html = document.documentElement;

        var docHeight = Math.max(body.scrollHeight, body.offsetHeight,
                               html.clientHeight, html.scrollHeight, html.offsetHeight);
        var currentScroll = (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
        if (((docHeight * 75) / 100) < currentScroll) {
            if (!isBusy) {
                fetchData()
            }
        }
    }

    function fetchData(){
        isBusy = true;
        $.ajax({
            cache: !1,
            type: "POST",
            data: $.toJSON(dataToPost_with_lastSearchedDate),
            contentType: "application/json; charset=utf-8",
            url: requestUrlToFetch_JSON_Data,
            success: function (response_JSON_data) {
                // Parse this JSON data and Append HTML to any div you want on Your Page 
                doStuff(response_JSON_data);
                lastSearchedDate =  new Date();
                isBusy = false;
            },
            error: function (xhr, ajaxOptions, thrownError) {
                alert(ajaxOptions);
                alert(thrownError);
                alert(xhr.status);
            }
        });
    }

    function OnFirstLoad() {
        fetchData();
        if (document.attachEvent) {
            document.attachEvent('onscroll', scrollEvent);
        } else if (document.addEventListener) {
            document.addEventListener('scroll', scrollEvent, false);
        }
    }

    window.onload = OnFirstLoad;

请注意,我们使用的是 javascript 日期,需要在我们提出请求的服务器网页/页面方法中解析(使用 DateTime.ParseExact)。

于 2013-11-12T11:24:59.587 回答
0

在这里查看http://www.w3schools.com/html/html5_serversentevents.asp以获取使用 html5 的服务器发送事件,这是 twitter 和 Facebook 使用的。

于 2013-11-18T00:01:56.650 回答
0

尝试这样的事情,我从未实现过可能对你有用

两者的想法是您运行一个等待连接的服务器文件(用 PHP 编写)。一旦连接到一个或多个客户端,就可以双向推送数据。那里有一些 PHP WebSocket 项目。看看这个:

http://code.google.com/p/phpwebsocket

node.js => http://nodejs.org/

http://net.tutsplus.com/tutorials/javascript-ajax/learning-serverside-javascript-with-node-js/

BinaryJS => http://binaryjs.com/

http://ajaxpatterns.org/HTTP_Streaming

于 2013-11-16T13:03:12.047 回答