我在这里遇到了一些噩梦,所以任何帮助将不胜感激!首先,我将解释我正在尝试做什么:
我正在尝试实现一个如下所述的系统:使用 Yii 框架在我的本地主机 MAMP 服务器上 https://stackoverflow.com/a/1086448/1034392。我有一个函数可以检查数据库中是否有任何新通知 - 如果有,它会解析它们并对它们进行 json 编码。我每 5 秒调用一次 while 循环。
所以:转到/user/unreadNotifications 会触发以下内容
Yii::log('test'); // to check it's getting called
$this->layout=false;
header('Content-Type: application/json');
// LONG POLLING
while (Yii::app()->user->getNotifications() == null) {
sleep(5);
}
echo Yii::app()->user->getNotifications(); // prints out json if new notification
Yii::app()->end();
return;
这工作正常 - 转到浏览器中的链接并验证了 json 响应 - 一切都很好。
然后我尝试了各种jQuery的东西来让它工作......我发现的唯一工作方法是使用带有 POST 类型的$.ajax
,但仅在有等待通知时(因此返回一些 json)。 $.get
或$.post
被"中止"(显示在Firebug中),但URL被调用(因为我可以看到日志文件已更新) - 奇怪。
我使用 $.get
的原始设置是:
<script type="text/javascript">
function notificationPoll() {
$.get('<?php echo Yii::app()->createUrl('user/unreadNotifications') ?>','', function(result) {
$.each(result.events, function(events) {
alert('New Notification!');
});
notificationPoll();
}, 'json');
}
</script>
<script type="text/javascript">
$(document).ready(function() {
$.ajaxSetup({
timeout: 60 //set a global ajax timeout of a minute
});
notificationPoll();
});
</script>
由于某种原因,这只会被"中止"。我已经尝试使用"jsonp",即使它不是 CORS 请求。但这也行不通。
这似乎无处可去!任何人都可以参与吗?
非常感谢
您必须确保函数在合理的时间内终止。你可以做的是这样的:
$ttl = 10;
while ($ttl--) {
$json = Yii::app()->user->getNotifications();
if (null != $json) {
break;
}
sleep(1);
}
if (null == $json) {
$json = json_encode(array(
'nothing' => true
));
}
header('Content-Type: application/json');
echo $json;
Yii::app()->end();
return;
您可以使用 setInterval() 将轮询函数设置为计时器。该函数现在将每 10 秒调用一次,您可能需要设置一个信号量以避免在上一次迭代返回之前调用它:
var timer = setInterval(
function() {
if (this.calling) {
return;
}
var fn = this;
fn.calling = true;
$.post(url)
.done(function(data) {
..
})
.always(function() {
fn.calling = false;
});
},
10000
);
然后 AJAX 中的轮询函数需要检查(在 .done()
中)回调)通知是否存在:
function(data) {
if (data.hasOwnProperty('nothing')) {
alert('No notifications');
return;
}
console.log(data);
...
}
现在,一件重要的事情是您的通知是什么样的。在这里,我假设它是一个 JSON 编码的字符串。但是如果它是 Yii 函数返回的数组或对象,则需要处理它的编码。这可能更干净,没有任何IF:
header('Content-Type: ...
die(json_encode(
array(
'status' => 'success',
'notification' => $json /* This is NULL or an array */
)
// Javascript side we check that data.notification is not null.
));
解码已经由 jQuery 处理,所以上面的变量 "data" 已经是一个 Javascript 对象,你不需要调用 JSON.parse
。不过,您可以检查data
是否是一个对象,以及它是否具有预期的属性。这将警告您任何错误。
要处理到另一个页面的导航,您可以将轮询 Javascript 函数的setInterval()
提供的计时器 ID 存储在全局变量中,并在页面调用 onUnload()
以停用轮询时删除计时器。
如果没有通知,getNotifications 会返回什么? jQuery 期望返回 JSON 格式,但当您只回显空字符串时,请求会失败,因为响应的格式不是 JSON。确保每次都回显 JSON 字符串。
怎么样。我假设$。(get) 位于一个名为 notificationPoll() 的函数中;完成后将重新调用。
$.ajax({
url: event_feed_href,
async: false,
timeout: 60000,
done: function(data) {
var got_json=false;
try {
var json = JSON.parse(data);
got_json=true;
}
catch(e) {
// failed to return JSON data
alert('Wierd!');
}
if(got_json) {
// process json data
alert('New Notification!');
}
},
always: function() {
notificationPoll();
}
});
我已经使用done并且总是在这里,因为jQuery所说的是贬低成功:失败:
我对代码中止感兴趣,可能会有你的答案。它可能由于多种原因而发生
- Query.get 失败。由于任何原因,Ajax 调用不起作用。解析错误。
- 糟糕的JavaScript语法。例如:成功处理程序中的代码需要输入参数中的 events 属性,这可能不为 true。
对于jQuery.get,正如jQuery.get(https://api.jquery.com/jQuery.get/)文档中所建议的那样,该函数可能会静默失败,我建议使用.ajaxError来查看get是否失败。
如果使用 jQuery.get() 的请求返回错误代码,它将静默失败,除非脚本还调用了全局 .ajaxError() 方法。或者,从 jQuery 1.5 开始,jQuery.get() 返回的 jqXHR 对象的 .error() 方法也可用于错误处理。
对于javascript语法错误,我建议逐步完成firebug调试器。在成功处理程序的第一行添加一个断点,然后从那里单步执行每一行。这很乏味,但它有效。