我在使用 Javascript 实例变量时遇到困难。我正在尝试一种简单的方法来刷新聊天页面,寻找新消息。 AJAX 调用提供 mid
,即要返回的最低消息 ID。这允许调用仅询问最近的消息,而不是所有消息。
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);
这会导致所有消息被一遍又一遍地打印出来。
我知道它还有其他错误,但我现在正在尝试解决的主要问题是实例变量的使用。或者我应该采取其他方法来做到这一点?
更新:更新了代码以反射(reflect)答案,但它仍然不起作用:
$(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 调用,然后停止。另外,当我在上面标记的“break here”行上中断时,Firebug 不会显示 refresher
或 _latest_mid
的值。我是否正确地将 refresher
传递到闭包中?
更新 3: 现在它不再停止进行 AJAX 调用。也许它有时会进行多次调用的原因是 setInterval()
在第一个请求返回并更新 _latest_mid
之前触发多个请求。
如何使用 JQuery Ajax 框架来防止这种情况发生?
最佳答案
试试这个:
setInterval($.proxy(messageRefresher, "refresh"), 1000);
问题是您需要确保您的对象(messageRefresher)用作调用“刷新”函数的“上下文”。仅将其声明为原型(prototype)的一部分这一事实并不能确保“this”始终是该对象的实例。事实上,“这个”几乎可以是任何东西。
jQuery 中的(相当新的)“proxy”方法返回对辅助函数的引用,该函数将使用您需要的对象作为上下文(即“refresh”中的“this”)来调用您的函数(“refresh”) ”)。
还有第一行,你只是提到了实例变量,你不需要它;它实际上没有做任何事情。
编辑更多说明。
任何 Javascript 函数内的“this”变量,无论如何或在何处声明,在每次不同的调用时都会获取其值。它不是该功能的永久部分;实际上,它就像传递给函数的有些特殊的参数。
在上面的例子中,您在传递给 $.getJSON
的函数中有一行代码引用“this”。您想要的是让“this”引用表示您的“messageRefresher”对象,对吗?好吧,就目前情况而言,它没有理由具有这样的值(value)。
我不知道为什么你要这样拆分“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...");
}
});
}
关于Javascript实例变量语法(AJAX页面刷新),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2594726/