Синтаксис переменной экземпляра Javascript (обновление страницы AJAX) - PullRequest
2 голосов
/ 07 апреля 2010

У меня проблемы с переменными экземпляра Javascript.Я пытаюсь сделать простой способ обновить страницу чата, ища новые сообщения.Вызов AJAX предоставляет mid или самый низкий идентификатор сообщения, который должен быть возвращен.Это позволяет звонку запрашивать только самые последние сообщения, а не все.

MessageRefresher.prototype._latest_mid;

function MessageRefresher(latest_mid) {
    this._latest_mid = latest_mid; // it thinks `this` refers to the MessageRefresher object
}

MessageRefresher.prototype.refresh = function () {
    refreshMessages(this._latest_mid); // it thinks `this` refers to the window
    this._latest_mid++;
}

function refreshMessages(latest_mid) {
    $.getJSON('API/read_messages', { room_id: $.getUrlVar('key'), mid: latest_mid }, function (messages) {
        for (var i = 0; i < messages[0].length; i++) {
            var newChild = sprintf("<li>%s: %s</li>", messages[1][i], messages[0][i]);
            $("#messages").append(newChild);
        }
    });

    var messageRefresher = new MessageRefresher(0);
    setInterval(messageRefresher.refresh, 1000);

Это приводит к тому, что все сообщения выводятся на печать снова и снова.

IЯ знаю, что у него есть другие ошибки, но сейчас я пытаюсь решить главную проблему - использование переменной экземпляра.Или есть другой способ сделать это?

ОБНОВЛЕНИЕ: Обновлен код для отображения ответов, но он все еще не работает:

$(document).ready(function () {

    var messageRefresher = new MessageRefresher(0);
    setInterval($.proxy(messageRefresher, "refresh"), 1000);

});

function MessageRefresher(latest_mid) {
    this._latest_mid = latest_mid; // it thinks `this` refers to the MessageRefresher object
}

MessageRefresher.prototype.refresh = function () {
    refreshMessages(this._latest_mid); // it thinks `this` refers to the window
}

function refreshMessages(latest_mid) {
    var refresher = this;
    $.getJSON('API/read_messages', { room_id: $.getUrlVar('key'), mid: latest_mid }, function (messages) {
        if (messages != null) {
            $("#messages-loading-msg").hide();
            for (var i = 0; i < messages[0].length; i++) {
                var newChild = sprintf("<li>%s: %s</li>", messages[1][i], messages[0][i]);
                $("#messages").append(newChild);
            }
        }
        else {
            $("#messages-loading-msg").text("No messages here. Say anything...");
        }

        refresher._latest_mid = messages[2];
    });
    }

Что я все еще делаю не так?Действительно ли this относится к messageRefresher или proxy?

ОБНОВЛЕНИЕ 2: Приближается, но все еще не совсем там:

$(document).ready(function () {

    $("#no-js-warning").empty();

    messageRefresher = new MessageRefresher(0);
    setInterval($.proxy(messageRefresher, "refresh"), 1000);

});

function MessageRefresher(latest_mid) {
    this._latest_mid = latest_mid; 
}

MessageRefresher.prototype.refresh = function () {
    var refresher = this;
    $.getJSON('API/read_messages', { room_id: $.getUrlVar('key'), mid: refresher._latest_mid }, function (messages) {
        if (messages != null) {
            $("#messages-loading-msg").hide();
            for (var i = 0; i < messages[0].length; i++) {
                var newChild = sprintf("<li>%s: %s</li>", messages[1][i], messages[0][i]);
                $("#messages").append(newChild);
            }
        }
        else {
            $("#messages-loading-msg").text("No messages here. Say anything...");
        }

        refresher._latest_mid = messages[2]; // break here
    });
}

Приведенный выше код выполняет два вызова AJAX, а затем останавливается.Кроме того, когда я разбиваю строку «разбить здесь», помеченную выше, Firebug не показывает значения для refresher или _latest_mid.Правильно ли я передаю refresher в замыкание?

ОБНОВЛЕНИЕ 3: Теперь он больше не прекращает совершать AJAX-вызовы.Возможно, причина, по которой он иногда делает несколько вызовов, заключается в том, что setInterval() запускает несколько запросов до того, как первый запрос вернулся, и обновил _latest_mid.

Как я могу использовать инфраструктуру JQuery Ajax для предотвращения этого

Ответы [ 2 ]

2 голосов
/ 07 апреля 2010

Попробуйте это:

setInterval($.proxy(messageRefresher, "refresh"), 1000);

Проблема в том, что вам нужно убедиться, что ваш объект (messageRefresher) используется в качестве "контекста" для вызова функции "refresh".Тот факт, что он объявлен как часть прототипа, не гарантирует, что «this» всегда будет экземпляром объекта.Фактически «this» может быть чем угодно.

(довольно новый) метод «proxy» в jQuery возвращает ссылку на вспомогательную функцию, которая будет вызывать вашу функцию («refresh») с объектомвам нужен контекст (то есть «this» внутри «refresh»).

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

edit Дополнительные пояснения.

Переменная "this" внутри любой функции Javascript, независимо от того, как и где она объявлена, получаетего значение при каждом отдельном вызове .Это не постоянная часть функции;по сути, это как особый параметр, передаваемый в функцию.

В вашем случае выше, у вас есть строка кода внутри функции, которую вы передаете $.getJSON, которая ссылается на "this".Что вы хотите, чтобы эта «this» ссылка означала ваш объект «messageRefresher», верно?Что ж, в его нынешнем виде нет никакой причины иметь это значение.

Я не знаю, почему у вас так "разделены" refreshMessages ".Сделайте так, чтобы это был метод «обновления».Затем сохраните указатель «this» в самом начале, и вы сможете вернуться из обработчика $.getJSON:

MessageRefresher.prototype.refresh = function () {
  var refresher = this;
  $.getJSON('API/read_messages', { room_id: $.getUrlVar('key'), mid: latest_mid }, function (messages) {
    if (messages.length > 0) {
        $("#messages-loading-msg").empty();
        for (var i = 0; i < messages[0].length; i++) {
            var newChild = sprintf("<li>%s: %s</li>", messages[1][i], messages[0][i]);
            $("#messages").append(newChild);
        }
        refresher._latest_mid = messages[2];
    }
    else {
        $("#messages-loading-msg").text("No messages here. Say anything...");
    }

  });
 }  
1 голос
/ 07 апреля 2010

Это потому, что вы берете функцию и назначаете ей интервал. Вы передали объект функции в setInterval, поэтому он не отслеживает своего владельца.

Функция, вызванная из интервала, будет находиться в области видимости глобального объекта. Вот как это исправить.

setInterval(function() {
    //this == window normally

    messageRefresher.refresh();
    //method invocation, so refresh will be bound
    //to the messageRefresher instance
}, 1000);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...