Я делаю систему разговоров, где 2 человека могут общаться друг с другом. Я сделал функцию AJAX, которая обновляет поле DIV, содержащее сообщения каждые 2 секунды.

Это работает как задумано, после пользователь написал сообщение. Почему вызов 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;
    });
});
1
Patrick Reck 24 Янв 2013 в 14:13

3 ответа

Лучший ответ

Вы должны предоставлять функции вместо строк для setTimeout / setInterval функций. А также вам не нужно устанавливать интервал при загрузке окна. Вы можете просто сохранить его как часть DOM:

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

Кажется, все остальное должно работать так, как и ожидалось, до тех пор, пока ваша посылка работает, когда данные не принимаются (ref 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();

});
2
Robert Koritnik 24 Янв 2013 в 10:55

Вам не нужен window.onload в вашем документе готовый вызов.

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

Этого должно быть достаточно, чтобы начать.

Как и сейчас, когда DOM готов, вы просите его дождаться загрузки окна ... но к этому моменту оно уже загружено, поэтому ничего не происходит.

0
minikomi 24 Янв 2013 в 10:18

Проблема в том, что updateMessages() пытается отправить datastring на сервер, но он не заполняется, пока не будет запущена функция .submit().

Я не знаю, что вы должны добавить туда, так как я не знаю, что ожидает сценарий mail/ajaxupdate. Если это вызывается, когда ничего не происходит, я подозреваю, что данные формы вообще не нужны, поэтому вы можете указать пустую строку.

Держу пари, если вы проверите консоль Javascript, вы увидите несколько сообщений об ошибках при попытке сериализации undefined.

1
Barmar 24 Янв 2013 в 10:21