head rush ajax chapter3 异步应用程序
异步是指当服务器在处理你的请求的时候,你不用等候,可以继续做你该做的事,服务器如果完成你的请求自然会通知你。同步的请求会等候来自服务器的响应,然后才能继续做别的事。
例如你有2个咖啡机,即使其中的一个正在工作,你还可以使用剩下的一个煮咖啡,两个服务互不影响。
一个请求对象可以做出多个请求,但是一次只能追踪一个请求在服务器上的进展。后面的请求会覆盖掉前面的请求。这时需要多个请求对象来处理不同的请求。
当服务器需要一段时间才能把响应送回,或者用户要在网页或表单上一次做多件事,这类应用最好采用异步方式。
DOM允许你改变页面内容而不需要重载页面。
coffee.html
<html>
<head>
<title>Ajax-powered Coffee Maker</title>
<link rel="stylesheet" type="text/css" href="coffee.css" />
<script type="text/javascript" src="ajax.js"> </script>
<script type="text/javascript" src="coffee.js"> </script>
<script type="text/javascript" src="text-utils.js"> </script>
</head>
<body>
<div id="header">
<h1>Ajax-powered Coffee Maker</h1>
</div>
<div id="wrapper">
<div id="coffeemaker1">
<h2>Coffee Maker #1</h2>
<p><img src="images/CoffeeMaker1.gif" alt="Coffee Maker #1" /></p>
<div id="coffeemaker1-status">Idle</div>
</div>
<div id="coffeeorder">
<p><img src="images/coffeeMugWithBeans.jpg" alt="Coffee Pot 1" /></p>
<h2>Place your coffee order here:</h2>
<div id="controls1">
<form>
<p>Name: <input type="text" name="name" id="name" /></p>
<h3>Size</h3>
<p>
<input type="radio" name="size"
value="small" checked="true">Small</input>
<input type="radio" name="size"
value="medium">Medium</input>
<input type="radio" name="size"
value="large">Large</input>
</p>
<h3>Beverage</h3>
<p>
<input type="radio" name="beverage"
value="mocha" checked="true">Mocha</input>
<input type="radio" name="beverage"
value="latte">Latte</input>
<input type="radio" name="beverage"
value="cappucino">Cappucino</input>
</p>
<p>
<input type="button"
onClick="orderCoffee();"
value="Order Coffee" />
</p>
</form>
</div>
</div>
<div id="coffeemaker2">
<h2>Coffee Maker #2</h2>
<p><img src="images/CoffeeMaker2.gif" alt="Coffee Maker #2" /></p>
<div id="coffeemaker2-status">Idle</div>
</div>
<p id="clear"></p>
</div>
</body>
</html>
ajax.js
function createRequest() {
var request = null;
try {
request = new XMLHttpRequest();
} catch (trymicrosoft) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
request = null;
}
}
}
if (request == null) {
alert("Error creating request object!");
} else {
return request;//如果请求创建成功,则把它返回
}
}
//创建两个请求对象
var request1 = createRequest();//静态的js(不再任何函数内部)被加载进html中就会被执行
var request2 = createRequest();
coffee.js
function sendRequest(request, url) {
request.onreadystatechange = serveDrink;//回调函数
request.open("GET", url, true);
request.send(null);
}
function getSize() {
var sizeGroup = document.forms[0].size;//web中的第一个form,size其中的元素名字
for (i=0; i<sizeGroup.length; i++) {
if (sizeGroup[i].checked == true) {//依次检测哪个radio被选中
return sizeGroup[i].value;
}
}
}
function getBeverage() {
var beverageGroup = document.forms[0].beverage;
for (i=0; i<beverageGroup.length; i++) {
if (beverageGroup[i].checked == true) {
return beverageGroup[i].value;
}
}
}
function orderCoffee() {
var name = document.getElementById("name").value;
var beverage = getBeverage();
var size = getSize();
var coffeemakerStatusDiv1 =
document.getElementById("coffeemaker1-status");
var status = getText(coffeemakerStatusDiv1);//检查第一个coffee机的状态
if (status == "Idle") {//如果他空闲,就让他服务
replaceText(coffeemakerStatusDiv1, "Brewing " + name + "'s " +
size + " " + beverage);
document.forms[0].reset();//清空表单
var url = "coffeemaker.php?name=" + escape(name) +
"&size=" + escape(size) +
"&beverage=" + escape(beverage) +
"&coffeemaker=1";
sendRequest(request1, url);//将第一个请求送到第一个咖啡机
} else {
var coffeemakerStatusDiv2 =
document.getElementById("coffeemaker2-status");
status = getText(coffeemakerStatusDiv2);
if (status == "Idle") {
replaceText(coffeemakerStatusDiv2, "Brewing " + name + "'s " +
size + " " + beverage);
document.forms[0].reset();
var url = "coffeemaker.php?name=" + escape(name) +
"&size=" + escape(size) +
"&beverage=" + escape(beverage) +
"&coffeemaker=2";
sendRequest(request2, url);//将第二个请求送到第二个咖啡机
} else {//大家都很忙啊
alert("Sorry! Both coffee makers are busy. " +
"Try again later.");
document.forms[0].reset();
}
}
}
function serveDrink() {
if (request1.readyState == 4) {
if (request1.status == 200) {//处理第一个请求对象
var response = request1.responseText;//获得响应数据
var whichCoffeemaker = response.substring(0, 1);//取出字符串中第一个字符
var name = response.substring(1, response.length);//取得第二个字符到最后的所有字符
if (whichCoffeemaker == "1") {//更改咖啡机状态为空闲
var coffeemakerStatusDiv1 =
document.getElementById("coffeemaker1-status");
replaceText(coffeemakerStatusDiv1, "Idle");
} else {
var coffeemakerStatusDiv2 =
document.getElementById("coffeemaker2-status");
replaceText(coffeemakerStatusDiv2, "Idle");
}
alert(name + ", your coffee is ready!");
request1 = createRequest();//一旦这个请求结束,必须创建新的请求对象以清除原有的请求对象
} else
alert("Error! Request status is " + request1.status);
} else if (request2.readyState == 4) {//处理第二个请求对象
if (request2.status == 200) {
var response = request2.responseText;
var whichCoffeemaker = response.substring(0, 1);
var name = response.substring(1, response.length);
if (whichCoffeemaker == "1") {
var coffeemakerStatusDiv1 =
document.getElementById("coffeemaker1-status");
replaceText(coffeemakerStatusDiv1, "Idle");
} else {
var coffeemakerStatusDiv2 =
document.getElementById("coffeemaker2-status");
replaceText(coffeemakerStatusDiv2, "Idle");
}
alert(name + ", your coffee is ready!");
request2 = createRequest();
} else
alert("Error! Request status is " + request2.status);
}
}
coffemaker.php
<?php
$name = $_REQUEST['name'];
$size = $_REQUEST['size'];
$beverage = $_REQUEST['beverage'];
$coffeemaker = $_REQUEST['coffeemaker'];
for ($i = 0; $i < 50000000; $i++) {//用延迟时间来模拟煮咖啡
// brewing
}
echo $coffeemaker . $name;
?>
例如你有2个咖啡机,即使其中的一个正在工作,你还可以使用剩下的一个煮咖啡,两个服务互不影响。
一个请求对象可以做出多个请求,但是一次只能追踪一个请求在服务器上的进展。后面的请求会覆盖掉前面的请求。这时需要多个请求对象来处理不同的请求。
当服务器需要一段时间才能把响应送回,或者用户要在网页或表单上一次做多件事,这类应用最好采用异步方式。
DOM允许你改变页面内容而不需要重载页面。
coffee.html
<html>
<head>
<title>Ajax-powered Coffee Maker</title>
<link rel="stylesheet" type="text/css" href="coffee.css" />
<script type="text/javascript" src="ajax.js"> </script>
<script type="text/javascript" src="coffee.js"> </script>
<script type="text/javascript" src="text-utils.js"> </script>
</head>
<body>
<div id="header">
<h1>Ajax-powered Coffee Maker</h1>
</div>
<div id="wrapper">
<div id="coffeemaker1">
<h2>Coffee Maker #1</h2>
<p><img src="images/CoffeeMaker1.gif" alt="Coffee Maker #1" /></p>
<div id="coffeemaker1-status">Idle</div>
</div>
<div id="coffeeorder">
<p><img src="images/coffeeMugWithBeans.jpg" alt="Coffee Pot 1" /></p>
<h2>Place your coffee order here:</h2>
<div id="controls1">
<form>
<p>Name: <input type="text" name="name" id="name" /></p>
<h3>Size</h3>
<p>
<input type="radio" name="size"
value="small" checked="true">Small</input>
<input type="radio" name="size"
value="medium">Medium</input>
<input type="radio" name="size"
value="large">Large</input>
</p>
<h3>Beverage</h3>
<p>
<input type="radio" name="beverage"
value="mocha" checked="true">Mocha</input>
<input type="radio" name="beverage"
value="latte">Latte</input>
<input type="radio" name="beverage"
value="cappucino">Cappucino</input>
</p>
<p>
<input type="button"
onClick="orderCoffee();"
value="Order Coffee" />
</p>
</form>
</div>
</div>
<div id="coffeemaker2">
<h2>Coffee Maker #2</h2>
<p><img src="images/CoffeeMaker2.gif" alt="Coffee Maker #2" /></p>
<div id="coffeemaker2-status">Idle</div>
</div>
<p id="clear"></p>
</div>
</body>
</html>
ajax.js
function createRequest() {
var request = null;
try {
request = new XMLHttpRequest();
} catch (trymicrosoft) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
request = null;
}
}
}
if (request == null) {
alert("Error creating request object!");
} else {
return request;//如果请求创建成功,则把它返回
}
}
//创建两个请求对象
var request1 = createRequest();//静态的js(不再任何函数内部)被加载进html中就会被执行
var request2 = createRequest();
coffee.js
function sendRequest(request, url) {
request.onreadystatechange = serveDrink;//回调函数
request.open("GET", url, true);
request.send(null);
}
function getSize() {
var sizeGroup = document.forms[0].size;//web中的第一个form,size其中的元素名字
for (i=0; i<sizeGroup.length; i++) {
if (sizeGroup[i].checked == true) {//依次检测哪个radio被选中
return sizeGroup[i].value;
}
}
}
function getBeverage() {
var beverageGroup = document.forms[0].beverage;
for (i=0; i<beverageGroup.length; i++) {
if (beverageGroup[i].checked == true) {
return beverageGroup[i].value;
}
}
}
function orderCoffee() {
var name = document.getElementById("name").value;
var beverage = getBeverage();
var size = getSize();
var coffeemakerStatusDiv1 =
document.getElementById("coffeemaker1-status");
var status = getText(coffeemakerStatusDiv1);//检查第一个coffee机的状态
if (status == "Idle") {//如果他空闲,就让他服务
replaceText(coffeemakerStatusDiv1, "Brewing " + name + "'s " +
size + " " + beverage);
document.forms[0].reset();//清空表单
var url = "coffeemaker.php?name=" + escape(name) +
"&size=" + escape(size) +
"&beverage=" + escape(beverage) +
"&coffeemaker=1";
sendRequest(request1, url);//将第一个请求送到第一个咖啡机
} else {
var coffeemakerStatusDiv2 =
document.getElementById("coffeemaker2-status");
status = getText(coffeemakerStatusDiv2);
if (status == "Idle") {
replaceText(coffeemakerStatusDiv2, "Brewing " + name + "'s " +
size + " " + beverage);
document.forms[0].reset();
var url = "coffeemaker.php?name=" + escape(name) +
"&size=" + escape(size) +
"&beverage=" + escape(beverage) +
"&coffeemaker=2";
sendRequest(request2, url);//将第二个请求送到第二个咖啡机
} else {//大家都很忙啊
alert("Sorry! Both coffee makers are busy. " +
"Try again later.");
document.forms[0].reset();
}
}
}
function serveDrink() {
if (request1.readyState == 4) {
if (request1.status == 200) {//处理第一个请求对象
var response = request1.responseText;//获得响应数据
var whichCoffeemaker = response.substring(0, 1);//取出字符串中第一个字符
var name = response.substring(1, response.length);//取得第二个字符到最后的所有字符
if (whichCoffeemaker == "1") {//更改咖啡机状态为空闲
var coffeemakerStatusDiv1 =
document.getElementById("coffeemaker1-status");
replaceText(coffeemakerStatusDiv1, "Idle");
} else {
var coffeemakerStatusDiv2 =
document.getElementById("coffeemaker2-status");
replaceText(coffeemakerStatusDiv2, "Idle");
}
alert(name + ", your coffee is ready!");
request1 = createRequest();//一旦这个请求结束,必须创建新的请求对象以清除原有的请求对象
} else
alert("Error! Request status is " + request1.status);
} else if (request2.readyState == 4) {//处理第二个请求对象
if (request2.status == 200) {
var response = request2.responseText;
var whichCoffeemaker = response.substring(0, 1);
var name = response.substring(1, response.length);
if (whichCoffeemaker == "1") {
var coffeemakerStatusDiv1 =
document.getElementById("coffeemaker1-status");
replaceText(coffeemakerStatusDiv1, "Idle");
} else {
var coffeemakerStatusDiv2 =
document.getElementById("coffeemaker2-status");
replaceText(coffeemakerStatusDiv2, "Idle");
}
alert(name + ", your coffee is ready!");
request2 = createRequest();
} else
alert("Error! Request status is " + request2.status);
}
}
coffemaker.php
<?php
$name = $_REQUEST['name'];
$size = $_REQUEST['size'];
$beverage = $_REQUEST['beverage'];
$coffeemaker = $_REQUEST['coffeemaker'];
for ($i = 0; $i < 50000000; $i++) {//用延迟时间来模拟煮咖啡
// brewing
}
echo $coffeemaker . $name;
?>