Это проще, чем я изначально думал ... В основном у вас есть страница, которая ничего не делает, пока данные, которые вы хотите отправить, не будут доступны (скажем, не придет новое сообщение).
Вот действительно простой пример, который отправляет простую строку через 2-10 секунд. 1 из 3 шансов вернуть ошибку 404 (чтобы показать обработку ошибок в следующем примере Javascript)
msgsrv.php
<?php
if(rand(1,3) == 1){
/* Fake an error */
header("HTTP/1.0 404 Not Found");
die();
}
/* Send a string after a random number of seconds (2-10) */
sleep(rand(2,10));
echo("Hi! Have a random number: " . rand(1,10));
?>
Примечание. На реальном сайте запуск этого на обычном веб-сервере, таком как Apache, быстро свяжет все "рабочие потоки" и оставит его неспособным отвечать на другие запросы. Есть способы обойти это, но рекомендуется написать «сервер длительного опроса» в чем-то вроде скрученного Python, который не полагается на один поток на запрос. cometD - популярное приложение (доступно на нескольких языках), а Tornado - это новый фреймворк, созданный специально для таких задач (он был построен для кода длинного опроса FriendFeed) ... но, как простой пример, Apache больше чем адекватно! Этот скрипт можно легко написать на любом языке (я выбрал Apache / PHP, поскольку они очень распространены, и мне довелось запускать их локально)
Затем в Javascript вы запрашиваете указанный выше файл (msg_srv.php
) и ждете ответа. Когда вы его получаете, вы действуете в соответствии с данными. Затем вы запрашиваете файл и снова ждете, действуете в соответствии с данными (и повторяете)
Ниже приводится пример такой страницы. Когда страница загружается, она отправляет начальный запрос для файла msgsrv.php
. Если это удается, мы добавляем сообщение в #messages
div, а затем через 1 секунду вызываем функцию waitForMsg снова, что вызывает ожидание.
1 секунда setTimeout()
- это действительно базовый ограничитель скорости, он отлично работает и без этого, но если msgsrv.php
always возвращает мгновенно (например, с синтаксической ошибкой) - вы заливаете браузер, и он может быстро зависнуть вверх. Это было бы лучше сделать, проверив, содержит ли файл действительный ответ JSON, и / или сохранив текущее количество запросов в минуту / секунду с соответствующей паузой.
Если страница ошибается, он добавляет ошибку в #messages
div, ждет 15 секунд, а затем пытается снова (аналогично тому, как мы ждем 1 секунду после каждого сообщения)
Этот подход хорош тем, что он очень устойчив. Если интернет-соединение клиента прерывается, оно истечет по таймауту, а затем попытается подключиться повторно - это зависит от того, как долго работает опрос, не требуется сложной обработки ошибок.
Во всяком случае, код long_poller.htm
, использующий фреймворк jQuery:
<html>
<head>
<title>BargePoller</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css" media="screen">
body{ background:#000;color:#fff;font-size:.9em; }
.msg{ background:#aaa;padding:.2em; border-bottom:1px #000 solid}
.old{ background-color:#246499;}
.new{ background-color:#3B9957;}
.error{ background-color:#992E36;}
</style>
<script type="text/javascript" charset="utf-8">
function addmsg(type, msg){
/* Simple helper to add a div.
type is the name of a CSS class (old/new/error).
msg is the contents of the div */
$("#messages").append(
"<div class='msg "+ type +"'>"+ msg +"</div>"
);
}
function waitForMsg(){
/* This requests the url "msgsrv.php"
When it complete (or errors)*/
$.ajax({
type: "GET",
url: "msgsrv.php",
async: true, /* If set to non-async, browser shows page as "Loading.."*/
cache: false,
timeout:50000, /* Timeout in ms */
success: function(data){ /* called when request to barge.php completes */
addmsg("new", data); /* Add response to a .msg div (with the "new" class)*/
setTimeout(
waitForMsg, /* Request next message */
1000 /* ..after 1 seconds */
);
},
error: function(XMLHttpRequest, textStatus, errorThrown){
addmsg("error", textStatus + " (" + errorThrown + ")");
setTimeout(
waitForMsg, /* Try again after.. */
15000); /* milliseconds (15seconds) */
}
});
};
$(document).ready(function(){
waitForMsg(); /* Start the inital request */
});
</script>
</head>
<body>
<div id="messages">
<div class="msg old">
BargePoll message requester!
</div>
</div>
</body>
</html>
person
dbr
schedule
02.12.2008