Ajax.Request( url, { method:method, parameters:para, postBody:xmlString, asynchronous:true, setRequestHeader:Object, onComplete:completeFun, onError:errorFun } }
发送异步请求。(此方法是为兼容 prototype.js 而写,调用风格与 prototype 一致,使用Ajax.Request此方法请在页面中加载此js文件)
参数
url
必选项。数据发送的目标地址。
method
可选项。数据提交的方式,默认值为get。常用的还有post。
parameters
当 method 为 get 时是可选项,为 post 时是必选项。发送的数据,其形式为: name1=valeu1& name2=value2&name3=value3......
postBody
可选项。客户端发送的 xml 格式字符串。如果启用 postBody,那么 parameters 将被忽略。
asynchronous
可选项。指定请求是否异步,默认为true(异步)。
setRequestHeader
指定请求的头部字串。其值类型为“名称值对”形式的对象,比如:{"If-Modified-Since":"0", "SOAPAction":"http://tempuri.org/SBS_WebService", ... ... }
onComplete
可选项。请求成功时执行的回调函数,该函数默认把当前使用 xmlhttp 对象作为第一个参数。
onError
可选项。请求异常时执行的回调函数,该函数默认把当前使用 xmlhttp 对象作为第一个参数。
返回值
当前使用的 xmlhttp 对象。
描述
发送异步请求,并返回 xmlhttp 对象,该对象内置有 abort() 方法,用于提前终止请求。异步请求成功则执行 onComplete,失败则执行 onError 。并返回 xmlhttp 对象。
Ajax.Request 是个接口完整的 Ajax 方法,是 myJSFrame 中所有其他 Ajax 方法的核心方法。
示例
示例一:
<script type="text/javascript" > var myAjax = new Ajax.Request( "http://www.happyshow.org/form.asp", { method:"post", //表单提交方式 parameters:"name=acai&age=26&sex=male", //提交的表单数据 setRequestHeader:{"If-Modified-Since":"0"}, //禁止读取缓存数据 onComplete:function(x){ //提交成功回调 alert(x.responseText); }, onError:function(x){ //提交失败回调 alert(x.statusText); } } ); </script>
注:parameters 参数若是不列出,我们在开发中对于Form 表单这样的数据 可以这样处理
parameters:Form.serialize('FormName') FormName 为页面中表单的 ID
示例二:
<script type="text/javascript" > var xmlString = "<root>" +"<people><name>caizhongqi</name><sex>male</sex></people>" +"<people><name>ahuang</name><sex>female</sex></people>" +" </root>"; var myAjax = new Ajax.Request( "http://www.happyshow.org/xmlform.asp", { method:"post", //表单提交方式 postBody:xmlString, //提交的xml setRequestHeader:{"content-Type":"text/xml"}, //指定发送的数据为 xml 文档(非字符串) onComplete:function(x){ //提交成功回调 alert(x.responseXML.xml); }, onError:function(x){ //提交失败回调 alert(x.statusText); } } ); </script>
为了支持 AJAX 功能。这个包定义了 Ajax.Request 类。
假如你有一个应用程序可以通过url http://yoursever/app/get_sales?empID=1234&year=1998与服务器通信。它返回下面这样的XML 响应。
<?xml version="1.0" encoding="utf-8" ?> <ajax-response> <response type="object" id="productDetails"> <monthly-sales> <employee-sales> <employee-id>1234</employee-id> <year-month>1998-01</year-month> <sales>$8,115.36</sales> </employee-sales> <employee-sales> <employee-id>1234</employee-id> <year-month>1998-02</year-month> <sales>$11,147.51</sales> </employee-sales> </monthly-sales> </response> </ajax-response>
用 Ajax.Request对象和服务器通信并且得到这段XML是非常简单的。下面的例子演示了它是如何完成的。
<script>
function searchSales()
{
var empID = $F('lstEmployees');
var y = $F('lstYears');
var url = 'http://yoursever/app/get_sales';
var pars = 'empID=' + empID + '&year=' + y;
var myAjax = new Ajax.Request(
url,
{method: 'get', parameters: pars, onComplete: showResponse}
);
}
function showResponse(originalRequest)
{
//put returned XML in the textarea
$('result').value = originalRequest.responseText;
}
</script>
<select id="lstEmployees" size="10" οnchange="searchSales()">
<option value="5">Buchanan, Steven</option>
<option value="8">Callahan, Laura</option>
<option value="1">Davolio, Nancy</option>
</select>
<select id="lstYears" size="3" οnchange="searchSales()">
<option selected="selected" value="1996">1996</option>
<option value="1997">1997</option>
<option value="1998">1998</option>
</select>
<br><textarea id=result cols=60 rows=10 ></textarea>
你看到传入 Ajax.Request构造方法的第二个对象了吗? 参数{method: 'get', parameters: pars, onComplete: showResponse} 表示一个匿名对象的真实写法。他表示你传入的这个对象有一个名为 method 值为 'get'的属性,另一个属性名为 parameters 包含HTTP请求的查询字符串,和一个onComplete 属性/方法包含函数showResponse。
还有一些其它的属性可以在这个对象里面定义和设置,如 asynchronous,可以为true 或 false 来决定AJAX对服务器的调用是否是异步的(默认值是 true)。
这个参数定义AJAX调用的选项。在我们的例子中,在第一个参数通过HTTP GET命令请求那个url,传入了变量 pars包含的查询字符串, Ajax.Request 对象在它完成接收响应的时候将调用showResponse 方法。
也许你知道, XMLHttpRequest在HTTP请求期间将报告进度情况。这个进度被描述为四个不同阶段:Loading, Loaded, Interactive, 或 Complete。你可以使 Ajax.Request 对象在任何阶段调用自定义方法 ,Complete 是最常用的一个。想调用自定义的方法只需要简单的在请求的选项参数中的名为 onXXXXX 属性/方法中提供自定义的方法对象。 就像我们例子中的 onComplete 。你传入的方法将会被用一个参数调用,这个参数是 XMLHttpRequest 对象自己。你将会用这个对象去得到返回的数据并且或许检查包含有在这次调用中的HTTP结果代码的 status 属性。
还有另外两个有用的选项用来处理结果。我们可以在onSuccess 选项处传入一个方法,当AJAX无误的执行完后调用, 相反的,也可以在onFailure选项处传入一个方法,当服务器端出现错误时调用。正如onXXXXX 选项传入的方法一样,这两个在被调用的时候也传入一个带有AJAX请求的XMLHttpRequest对象。
我们的例子没有用任何有趣的方式处理这个 XML响应, 我们只是把这段XML放进了一个文本域里面。对这个响应的一个典型的应用很可能就是找到其中的想要的信息,然后更新页面中的某些元素, 或者甚至可能做某些XSLT转换而在页面中产生一些HTML。
new Ajax.Request(url[, options])
初始化并处理一个 AJAX 请求.
该对象是一个具有多种用途的 AJAX 请求:它管理请求的生命周期,处理“样板文件”代码(boilerplate), 让你能够按照你的需要在指定的阶段插入所需的回调函数。
options
是一个可选的 hash 参数,除非你获取一个将会被 eval
自动执行的 Javascript 类型的响应,否则通常需要提供onComplete
和/或onSuccess
回调函数。
公用选项和回调函数的完整列表,请参见 Ajax 选项。
创建一个请求唯一恰当的方法是通过 new
操作符。在对象被创建后,就开始了请求过程, 对该对象的处理贯穿了请求的整个生命周期。
一个基本的样例
var url = '/proxy?url=' + encodeURIComponent('http://www.google.com/search?q=Prototype'); // 注意:使用 proxy 是为了避开 SOP(参见:SOP) new Ajax.Request(url, { method: 'get', onSuccess: function(transport) { var notice = $('notice'); if (transport.responseText.match(/href="http:\/\/prototypejs.org/)) notice.update('Yeah! You are in the Top 10!').setStyle({ background: '#dfd' }); else notice.update('Damn! You are beyond #10...').setStyle({ background: '#fdd' }); } } );
请求生命周期
在我们完美的请求对象下面,当然是 XMLHttpRequest
。请求定义的生命周期如下:
- 创建(Created)
- 初始化(Initialized)
- 请求发送(Request sent)
- 响应接收(Response being received)(可能发生多次,根据返回包的数目而定)
- 响应接收完成,请求结束(Response received)
你也可以参阅 Ajax 选项,Prototype 的 AJAX 对象定义了完整的回调系列,它们按照下述的顺序被触发:
-
onCreate
(实际上这是被AJAX 全局响应器
保留的回调)。 -
onUninitialized
(对应于“创建”[Created]) -
onLoading
(对应于“初始化”[Initialized]) -
onLoaded
(对应于“请求发送”[Request sent]) -
onInteractive
(对应于“响应接收”[Response being received]) -
on
XYZ(XYZ 表示响应的状态代码,参见状态代码)对应于指定的响应状态代码回调、onSuccess 或 onFailure(见下文) onComplete
最后两步对应于响应接收完成(Response received)。如果定义了一个与指定状态代码相关的回调函数,它将会被调用。否则,如果 onSuccess
被定义并且响应被认为是成功的(见下文),onSuccess
就会被调用,如果响应不成功并且定义了 onFailure
,则调用 onFailure
。onComplete
在上述回调结束后才会被调用。
一个关于可移植性的提示
依赖于浏览器对 XMLHttpRequest
的不同实现,一个或多个回调可能永远都不会被调用。尤其是 onLoaded
和onInteractive
,迄今为止仍不是一个稳赢的赌注。然而,全局的onCreate
、onUninitialized
以及最后的两个步骤还是可以保障的。
onSuccess
和 onFailure
, 未充分利用的回调
很多人使用 Ajax.Request
的方式在一定程度上仍然类似于使用原始的 XHR:即使他们只关心“成功”的响应, 仍定义一个 onComplete
回调,然后手动测试:
// 太糟糕了,有更好的做法! new Ajax.Request('/your/url', { onComplete: function(transport) { if (200 == transport.status) // yada yada yada } } );
首先,就像下面所描述的那样,你可以使用更好的“成功”检测:成功通常被定义为没有响应状态代码或者响应状态代码为 "2xy" 系列(如 201 也被认为是成功的)。参见下面的样例。
其次,你完全可以省略状态代码测试!Prototype 增加了指明成功或失败的回调函数,我们在上面已经列出。如果你仅对成功感兴趣, 可以采用如下方式:
new Ajax.Request('/your/url',{ onSuccess: function(transport){ // yada yada yada } } );
自动执行 Javascript 响应
如果一个 AJAX 请求遵循 SOP (译注:中文说明),并且它的响应的 content-type 与 Javascript 相关,responseText
属性的内容将会自动传递给 eval
。
这意味着若 AJAX 响应的内容是纯粹的 Javascript,你甚至不需要提供一个回调来处理它。这非常酷,不是吗?下面列出了 Prototype 能够处理的与 Javascript 相关的 MIME 类型:
application/ecmascript
application/javascript
application/x-ecmascript
application/x-javascript
text/ecmascript
text/javascript
text/x-ecmascript
text/x-javascript
MIME 类型字符串的检测不区分大小写。
可能常用的方法
请求对象的实例提供了一些方法,在回调函数中,你迟早会用到它们,尤其是当请求完成时。
1、是否是一个成功的响应?
success()
方法检测 XHR 的 staus
属性,它遵循以下的规则:未知的状态被认为是成功的, 2xy 系列状态代码也认为是成功的。通常这比你使用200 == transport.status
测试响应更为有效。
2、获取 HTTP 响应头
如果你使用 XHR 对象的 getResponseHeader
方法从 XHR 对象中获取响应头,会导致代码变得冗长, 并且有些实现在找不到指定头时,会引发异常。为简化这个处理过程,可以使用Ajax.Response#getHeader
方法,那些冗长的代码将由它来内置处理,并且发生异常时,它将返回一个null
值。
new Ajax.Request('/your/url', { onSuccess: function(response){ // 注意对 null 值的处理 if ((response.getHeader('Server') || '').match(/Apache/)) ++gApacheCount; // 其余的代码 } } );
3、执行 JSON 头
有时后端返回 JSON 文本不是通过响应内容,而是通过 X-JSON
头。在这种情况下,你甚至不需要自己执行返回的 JSON 文本,Prototype 自动完成了这项工作并将结果传递给Ajax.Response
对象的headerJSON
属性。 注意:如果指定的头不存在或者头的内容是非法的,这个属性将被设置为null
。
new Ajax.Request('/your/url', { onSuccess: function(transport) {transport.headerJSON}});
Ajax.Updater类是对Ajax.Request类的简化,使用该类不需要使用回调方法,该类自动讲服务器响应显示到某个容器。
下面就是一个简单的例子:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>输入提示示范</title>
<meta name="author" content="Yeeku.H.Lee" />
<meta name="website" content="http://www.crazyit.org" />
<meta http-equiv="Content-Type" content="text/html; charset=GBK" />
</head>
<body>
<h3>
请输入您喜欢的水果
</h3>
<div style="width: 280px; font-size: 9pt">
输入apple、banana、peach可看到明显效果:
</div>
<br />
<input id="favorite" name="favorite" type="text"
οnblur="$('tips').hide();" />
<img id="Loadingimg" src="img/indicator.gif" style="display: none" />
<div id="tips"
style="width: 160px; border: 1px solid menu; background-color: #ffffcc; display: none;"></div>
<script src="js/prototype-1.6.0.3.js" type="text/javascript"></script>
<script type="text/javascript">
//发送请求的函数
function searchFruit() {
//定义发送请求的服务器地址
var url = 'TipServlet';
//取得请求参数字符串
var params = $('favorite').serialize();
//创建Ajax.Updater对象,对应于发送一次请求
var myAjax = new Ajax.Updater(
//指定tips作为服务器响应的容器
'tips', url, {
//发送请求的方法
method : 'post',
//请求参数
parameters : params,
//指定Ajax交互结束后的回调函数,匿名函数——显示id为tips的元素
onComplete : function() {
$('tips').show();
}
});
}
//为表单域绑定事件监听器
new Form.Element.Observer("favorite", 0.5, searchFruit);
//定义Ajax事件的全局处理器
var myGlobalHandlers = {
//当开始Ajax交互时,激发该函数
onCreate : function() {
$('Loadingimg').show();
},
//当Ajax交互失败后,激发该函数。
onFailure : function() {
alert('对不起!\n页面加载出错!');
},
//当Ajax交互结束后,激发该函数。
onComplete : function() {
//如果所有Ajax交互都已完成,隐藏Loadingimg对象
if (Ajax.activeRequestCount == 0) {
$('Loadingimg').hide();
}
}
};
//为Ajax事件绑定全局事件处理器
Ajax.Responders.register(myGlobalHandlers);
</script>
</body>
</html>
Servlet代码:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TipServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//获取请求参数favorite
String hdchar = request.getParameter("favorite");
System.out.println(hdchar);
PrintWriter out = response.getWriter();
//如果请求参数是apple的前几个字符,则输出apple
if ("apple".startsWith(hdchar))
{
out.println("apple");
}
//如果请求参数是banana的前几个字符,则输出banana
else if("banana".startsWith(hdchar))
{
out.println("banana");
}
//如果请求参数是peach的前几个字符,则输出peach
else if("peach".startsWith(hdchar))
{
out.println("peach");
}
//否则将输出other fruit
else
{
out.println("other fruit");
}
}
}
Ruby 注意:
加authenticity_token:
:onchange => "$('waiting_3').style.display='block';new Ajax.Request('/admin/update', {asynchronous:true, evalScripts:true, parameters:'id='+this.value + '&authenticity_token=' + encodeURIComponent('#{form_authenticity_token()}')})"
或:在contropller中加上去除:
protect_from_forgery :except => :update