1

我正在制作一个可以让两个人互相聊天的对话系统。我制作了一个 AJAX 函数,它每 2 秒更新一次包含消息的 DIV 框。

在用户写完消息,这将按预期工作。为什么没有立即运行 AJAX 调用?

// SET AUTORUN updateMessages() EVERY 2 SECONDS
$(document).ready(function() {
    var interval
    window.onload = function(){
        interval = setInterval('updateMessages()', 2000);
    };
});

// UPDATE #mail_container_conversation
function updateMessages() {
    $.ajax({
        type: "POST",
        url: "<?php echo site_url(); ?>mail/ajaxupdate/<?php echo $user; ?>",
        data: dataString,
         
        success: function(data){
            $("#mail_container_conversation").html(data);
        }        
    });
}


// SEND NEW MESSAGE
$(function(){
    $("#mail_send").submit(function(){
        dataString = $("#mail_send").serialize();
         
        $.ajax({
        type: "POST",
        url: "<?php echo site_url(); ?>mail/send",
        data: dataString,
         
        success: function(data){
            updateMessages();
            $(".mail_conversation_answer_input").val('');
        }
                  
        });
                 
        return false;
    });
});
4

5 回答 5

2

如果您的其余代码正常工作,则问题可能出在此代码上:

$(document).ready(function() {
    var interval
    window.onload = function(){
        interval = setInterval('updateMessages()', 2000);
    };
});
  1. 无需将其附加到window.onload,因为您已经将其包装在 DOM-ready 回调中。
  2. 从调用中删除单引号和括号setInterval
  3. 只需将函数传递给 jQuery 方法,即可缩短 DOM 就绪回调。

试试这个:

$(function () {
    setInterval(updateMessages, 2000);
});

进一步改进 - 使用 AJAX 避免间隔:

在处理 AJAX 时,您应该避免使用间隔,因为如果服务器需要超过两秒的时间来响应,您最终可能会堆积对服务器的调用。setInterval不在乎您的服务器是否有时间响应,无论如何它都会每 2 秒调用一次。

我建议您改用超时,并在 Ajax 调用的完整回调中启动新的超时。

在您的情况下,它可能看起来像这样:

$(function () {
    // Make the first call immediately when the DOM is ready
    updateMessage();
});

function updateMessages() {
    $.ajax({
        type: "POST",
        url: "<?php echo site_url(); ?>mail/ajaxupdate/<?php echo $user; ?>",
        data: dataString,

        success: function(data){
            $("#mail_container_conversation").html(data);
            // Make a new call, 2 seconds after you've 
            // received a successful respose
            setTimeout(updateMessages, 2000);
        }        
    });
}
于 2013-01-24T10:18:29.590 回答
2

您应该向setTimeout/setInterval函数提供函数而不是字符串。而且您也无需设置窗口加载事件的时间间隔。你可以把它作为 DOM 的一部分准备好:

$(function() {
    updateMessages(); // don't wait 2 seconds for first update
    setInterval(updateMessages, 2000); // update every 2 seconds
});

只要您在没有收到数据时回发工作,其他一切似乎都应该按预期工作(参考dataString)。

我希望您确实意识到您正在使用隐含的全局变量并理解为什么这可能是一个大问题(dataString再次参考)。

我将如何重写你的代码

我会将您的整个代码重写为以下内容,删除隐含的全局变量dataString,不会用其他函数污染全局范围,并使用setTimeout在某些情况下可能会出现问题的间隔(尽管在您的情况下,因为它仅每 2 秒运行一次)如果没有额外的非常复杂的客户端脚本执行,应该不是问题)

我将所有内容都保留在函数闭包本地范围内:

$(function() {

    var timeout = null;

    var form = $("#mail_send").submit(function(evt){
        evt.preventDefault();
        $(".mail_conversation_answer_input", form).val("");
        updateMessages();
    });

    var updateMessages = function() {

        // we don'w want submit to interfere with auto-updates
        clearTimeout(timeout);

        $.ajax({
            type: "POST",
            url: "<?php echo site_url(); ?>mail/send",
            data: form.serialize(),
            success: function(data){
                $("#mail_container_conversation").html(data);
                timeout = setTimeout(updateMessages, 2000);
            }
        });
    };

    // start updating
    updateMessages();

});

此代码要求您的服务器端(在 上处理/mail/send)了解当没有发布任何内容(没有数据)时,它不会在对话中添加空行,而是知道这只是一个更新调用。此功能现在仅使用一个服务器端 URL,而不是其中的两个。如果您仍然需要两个,那么这段代码应该可以解决问题:

$(function() {

    var timeout = null;
    var url = {
        update: "<?php echo site_url();?>mail/ajaxupdate/<?php echo $user;?>",
        submit: "<?php echo site_url();?>mail/send",
        use: "update"
    };

    var form = $("#mail_send").submit(function(evt){
        evt.preventDefault();
        url.use = "submit";
        $(".mail_conversation_answer_input", form).val("");
        updateMessages();
    });

    var updateMessages = function() {

        // we don'w want submit to interfere with auto-updates
        clearTimeout(timeout);

        $.ajax({
            type: "POST",
            url: url[url.use],
            data: form.serialize(),
            success: function(data){
                $("#mail_container_conversation").html(data);
                url.use = "update";
                timeout = setTimeout(updateMessages, 2000);
            }
        });
    };

    // start updating
    updateMessages();

});
于 2013-01-24T10:19:20.060 回答
1

问题是它updateMessages()试图发送到服务器,但在函数运行datastring之前不会填写。.submit()

我不知道你应该在那里放什么,因为我不知道mail/ajaxupdate脚本期望什么。如果什么都没有发生时调用它,我怀疑根本不需要表单数据,所以你可以给出一个空字符串。

我敢打赌,如果您检查了 Javascript 控制台,您会看到一些关于尝试序列化的错误消息undefined

于 2013-01-24T10:21:43.033 回答
0

试一试

$(document).ready(function() {

  setInterval('updateMessages()', 2000);

});
于 2013-01-24T10:17:26.103 回答
0

您不需要window.onloadin your document ready 调用。

$(document).ready(function() {
    setInterval('updateMessages()', 2000);
});

这应该足以让它开始。

就像现在一样,一旦 DOM 准备就绪,您就会要求它等待窗口加载.. 但到那时它已经加载了,所以什么也没有发生。

于 2013-01-24T10:18:35.860 回答