มันง่ายกว่าที่ฉันคิดไว้ในตอนแรก .. โดยทั่วไปคุณมีหน้าเว็บที่ไม่ทำอะไรเลยจนกว่าจะมีข้อมูลที่คุณต้องการส่ง (พูดว่ามีข้อความใหม่มาถึง)
นี่คือตัวอย่างพื้นฐานจริง ๆ ซึ่งส่งสตริงง่าย ๆ หลังจาก 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 twistedซึ่งไม่ขึ้นอยู่กับหนึ่งเธรดต่อคำขอ cometDเป็นหนึ่งที่ได้รับความนิยม (ซึ่งมีให้บริการในหลายภาษา) และTornadoเป็นเฟรมเวิร์กใหม่ที่สร้างขึ้นเป็นพิเศษสำหรับงานดังกล่าว (มันถูกสร้างขึ้นสำหรับรหัสโพลแบบยาวของ FriendFeed) ... แต่เป็นตัวอย่างง่ายๆ Apache ก็เพียงพอแล้ว ! สคริปต์นี้สามารถเขียนได้อย่างง่ายดายในทุกภาษา (ฉันเลือก Apache / PHP เนื่องจากเป็นเรื่องธรรมดามากและฉันก็เรียกใช้พวกเขาในพื้นที่)
จากนั้นใน Javascript คุณขอไฟล์ด้านบน ( msg_srv.php
) และรอการตอบกลับ เมื่อคุณได้รับหนึ่งคุณดำเนินการกับข้อมูล จากนั้นคุณร้องขอไฟล์และรออีกครั้งดำเนินการกับข้อมูล (และทำซ้ำ)
สิ่งต่อไปนี้เป็นตัวอย่างของหน้าดังกล่าว .. เมื่อหน้าโหลดมันจะส่งคำขอเริ่มต้นสำหรับmsgsrv.php
ไฟล์ .. ถ้ามันประสบความสำเร็จเราผนวกข้อความไปยัง#messages
div แล้วหลังจาก 1 วินาทีที่เราเรียกใช้ฟังก์ชั่น waitForMsg อีกครั้ง ซึ่งก่อให้เกิดการรอคอย
1 ที่สองsetTimeout()
เป็นอัตราที่ limiter พื้นฐานจริงๆก็ทำงานได้ดีโดยไม่ต้องนี้ แต่ถ้าmsgsrv.php
เสมอจะส่งกลับทันที (ที่มีข้อผิดพลาดทางไวยากรณ์เช่น) - คุณน้ำท่วมเบราว์เซอร์และมันได้อย่างรวดเร็วสามารถแข็งขึ้น สิ่งนี้จะเป็นการดีกว่าถ้าตรวจสอบว่าไฟล์มีการตอบสนอง 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>