Javascript回调函数问题

时间:2009-03-15 03:32:18

标签: javascript jquery function callback

背景

我正在为我的网站编写异步评论系统,在阅读了大量关于如何实现这一目标的教程后,我开始从头开始构建一个。使用JSON请求提取注释并使用Javascript(jQuery)显示。当用户添加新注释时,它会通过环节,最后通过AJAX发送到后端,并将其添加到数据库中。在AJAX请求的成功部分,我让脚本清空注释,然后重新生成新列表(包括新帖子)并重新显示它们。

问题

虽然这一切都很好,但由于它使页面缩短了很长时间,因此它会让用户查看页面的时间更长。我想让它重新调整页面,直到评论列表的末尾(添加评论表单的位置)。它还重新启用了添加按钮,该按钮在点击它时被禁用,以防止不耐烦的人发送垃圾邮件。

$('#commentList').empty();
getComments('blog', $('input#blogId').val());
window.location = "#addComment";
$('#comAdd').removeAttr('disabled');

虽然这在理论上运作良好且良好,但似乎浏览器在getComments函数完成之前已经超前并处理window.location。所以我再读一遍并用谷歌搜索它似乎人们说(对于类似的问题)使用回调函数,所以我提出了这个:

$('#commentList').empty();
getComments('blog', $('input#blogId').val(), function() {
    window.location = "#addComment";
    $('#comAdd').removeAttr('disabled');
});

根据FireFox,这不会产生任何javascript错误,但回调函数中的任何内容都不起作用,它不会重新启用按钮,也不会更改window.location。

有什么想法吗?更好的方法去做吧?我有一个我似乎无法看到的明显错字吗?

谢谢!

更新

我的印象是回调函数是你可以使用的标准函数。

function getComments(type, id)
{

    $.getJSON("/ajax/"+type+"/comments?jsoncallback=&id="+id, function(data) {
        for (var x = 0; x < data.length; x++)
        {
            var div = $("<div>").addClass("comment").appendTo("#commentList");
            var fieldset = $("<fieldset>");
            var legend = $("<legend>").addClass("commentHeader");
            if ( data[x].url == "" )
            {
                legend.text((x+1) + ' - ' + data[x].name);
            }
            else
            {
                $("<a>").attr({href: data[x].url}).text((x+1) + ' - ' + data[x].name).appendTo(legend);
            }
            legend.appendTo(fieldset);
            $("<div>").addClass("date").text(data[x].timestamp).appendTo(fieldset);
            $("<p>").addClass("comment").text(data[x].content).appendTo(fieldset);
            fieldset.appendTo(div);
        }
    });

}

在文档就绪时调用此方法。拉出所有注释并在#commentList div中显示它们。当用户提交他/她的评论时,它会向PHP脚本执行一个AJAX请求,该脚本会将新评论添加到数据库中,一旦成功,我就会这样:

$('#commentList').empty();
getComments('blog', $('input#blogId').val());
window.location = "#addComment";
$('#comAdd').removeAttr('disabled');

删除页面中的所有评论。 使用JSON再次请求注释(包括用户新注释)。 将页面移动到#addComment锚点,这是他们的新评论将显示的位置。 重新启用添加评论按钮。

问题是浏览器在getComments函数完成之前执行window.location行渲染所有注释,因此随着页面的增长,用户看不到任何靠近新注释的位置。

2 个答案:

答案 0 :(得分:2)

我希望这里的问题是你的getComments()函数(需要更多详细信息)。你提供的第三个参数是回调,但该函数实际上是否使用回调?它在做什么?

某些jQuery函数提供回调,但这不是自动功能。如果您正在等待用户输入评论,则需要在他们点击“完成”或其他任何操作时触发相关事件。

好的,试试这个:

function get_comments(type, id, callback) {
  $.getJSON("/ajax/"+type+"/comments?jsoncallback=&id="+id, function(data) {
    for (var x = 0; x < data.length; x++) {
      var div = $("<div>").addClass("comment").appendTo("#commentList");
      var fieldset = $("<fieldset>");
      var legend = $("<legend>").addClass("commentHeader");
      if ( data[x].url == "" ) {
        legend.text((x+1) + ' - ' + data[x].name);
      } else {
        $("<a>").attr({href: data[x].url}).text((x+1) + ' - ' + data[x].name).appendTo(legend);
      }
      legend.appendTo(fieldset);
      $("<div>").addClass("date").text(data[x].timestamp).appendTo(fieldset);
      $("<p>").addClass("comment").text(data[x].content).appendTo(fieldset);
      fieldset.appendTo(div);
      if (typeof callback != 'undefined') {
        callback();
      }
    }
  });
}

注意:这里的区别在于第三个参数提供给get_comments(),这是一个回调函数,它将在$ .getJSON()回调结束时调用。那将为您提供您想要的正确订单。

我可能还建议不要像这样构建HTML,但要在页面中包含它,并在必要时隐藏/取消隐藏它。它往往比动态HTML更具性能并且问题更少(例如新的HTML,除非你使用$()。live()将没有相关的事件处理程序。)

编辑:根据评论使回调可选。使用上面的代码,您无需回调即可调用该函数。

答案 1 :(得分:0)

简单。重新启用按钮并在收到请求后转到锚点并处理信息。像这样:

function getComments(type, id)
{
    // ADDED
    $('#commentList').empty();

    $.getJSON("/ajax/"+type+"/comments?jsoncallback=&id="+id, function(data) {
        for (var x = 0; x < data.length; x++)
        {
                var div = $("<div>").addClass("comment").appendTo("#commentList");
                var fieldset = $("<fieldset>");
                var legend = $("<legend>").addClass("commentHeader");
                if ( data[x].url == "" )
                {
                        legend.text((x+1) + ' - ' + data[x].name);
                }
                else
                {
                        $("<a>").attr({href: data[x].url}).text((x+1) + ' - ' + data[x].name).appendTo(legend);
                }
                legend.appendTo(fieldset);
                    $("<div>").addClass("date").text(data[x].timestamp).appendTo(fieldset);
                    $("<p>").addClass("comment").text(data[x].content).appendTo(fieldset);
                fieldset.appendTo(div);
        }

        // ADDED
        window.location = "#addComment";
        $('#comAdd').removeAttr('disabled');
    });
}

个人意见:为什么不从特定日期获取评论,而不是提取所有评论?加载页面时,在响应中包含服务器时间。 Javascript使用它来查询幕后(自动检查新注释)。 JSON响应包括新的服务器时间,用于下一个响应。

您将如何处理已删除的评论?简单:在数据库表中有一个deleted_on列,查询它,并在JSON响应中将其与新帖子一起吐出。

建议:代替#addcomment,ID按时间戳注释。