今天在使用dojo进行异步请求动作的同时,加入了一个文件上传,由于不想引入struts等框架,采用了古老的jspsmartupload,结果用xhrPost异步提交时无论如何都没有反应,鉴于公司限网,只好回家查资料了。搜索一番发现dojo中想异步上传数据包,有一个专门的方法,就是使用dojo.io.iframe。
这里,顺带提一下dojo的XHR,XHR框架是dojo对ajax支持的一组方法,允许想服务器端发出get、post、put、delete请求,这些方法包括:xhrGet、xhrPost、xhrPut、xhrDelete。具体在前面转载的文章《用Dojo实现XHR、跨域、及其他Ajax请求》中描述的很清楚,有需要的可以去了解。
这里需要注意,所有这些函数都遵守相同的语法:接受一个属性配置对象作为参数。在这些对象中您可以定义您想要发出的Ajax请求的各个方面。再一次说明,这些选项在所有XHR函数中都是一样的。
这里列举一些比较常用的选项:
url:这是 HTTP 请求的 URL。它必须和发出这一请求的页面有同样的域和端口组合。
handleAs:允许您定义响应的处理格式,默认是 text,但是,json、javascript、xml、还有一些其他选项也可用。在本节后面您将看到一个创建 Ajax 请求的示例,使用一个处理 JSON 响应格式的回调函数。
form:<form> 元素的一个引用或者字符串 ID 表示。form 中每个字段的值将被同请求一起作为请求体发送。
content:一个对象,包含您想要传递给请求体中资源的参数。如果两者都提供,这个对象将与从 form 属性中获取的值混合在一起。
load:当 Ajax 请求返回一个成功响应消息时,执行此函数。响应数据和请求对象作为参数被传递到这个函数。
error:如果 Ajax 请求出现问题,该函数将被调用。如果在 Ajax 请求中定义的 URL 无效、请求超时或者发生其他 HTTP 错误,这将会出现。错误消息和请求对象被作为参数传递。
handle:该函数允许您将加载和错误回调函数合并到一个函数中(如果您确实不关心请求结果是成功或是出现错误,这将非常有用)。
这几种类型的请求对于构建一个REST风格的框架很有用,用xhrGet查看数据,xhrPost修改数据,xhrPut创建数据,xhrDelete删除数据,每一种类型的请求对应一种服务器端具体的操作。
XHR对于普通的Web请求具有很强的可操作性,但是对于像异步的上传文件等操作显得比较棘手,不过没关系,dojo已经为我们想到了这些。
dojo通过使用iframe的方式实现了这种高级的数据传输。dojo.io.iframe 是如何工作的呢?除了 XHR 对象之外还有什么方法可以实现表单的异步提交?其实这一切都很简单,dojo.io.iframe 首先会创建一个隐藏的 iframe 并插入到父页面的最后,然后设置此 iframe 的 src 属性为dojo-module-path/resources/blank.html(dojo-module-path 指 dojo 包所在的目录),iframe 页面的 onload 事件的处理函数被设置为父窗体的回调函数。接下来就是在 iframe 页面中发送请求,并接收服务器的响应。当 iframe 接收到服务器的反馈并加载完之后,父窗体的回调函数即被调用。
XHR 框架中的函数功能强大,使用方便。但是 XHR 框架的函数有一问题就是不能跨域访问,浏览器不允许 XHR 对象访问其他域的站点。
JSONP(JSONP Padding)就是为了解决跨域访问而产生的:
通过<javascript></javascript>标签访问封装JSON数据的地址
将要返回的数据封装为JSON对象
数据返回给浏览器,并被自动执行
这便是JSONP执行的基本流程,但是想要确定数据是否加载完成并不容易,通常的做法是设置一个回调方法,这个方法的名称被作为请求参数的一部分发送给服务器,服务器在将数据封装完整后,生成回调方法执行的代码,并将这些信息全部返回给客户端,当客户端执行返回数据时,回调方法也会被随之调用。
总结下来,传送文件则iframe,跨域访问则使用动态脚本,其余则选XHR框架。
转入正题,给大家整理一个简单的异步上传示例:
<script>
dojo.require(“dojo.io.iframe”);
</script>
首先引入,这里不多做介绍,然后,我们要建一个form表单:
<form id=”form1″ enctype=”multipart/form-data” method=”post”>
<table class=”style1″>
<tr>
<td>
文件名:</td>
<td align=”left”>
<input id=”txt_name” name=”txt_name” type=”text” /></td>
</tr>
<tr>
<td>
文件地址:</td>
<td align=”left”>
<input id=”f_img” name=”f_img” type=”file” /></td>
</tr>
<tr>
<td>
</td>
<td align=”left”>
<input id=”btn_submit” type=”submit” value=”submit” /></td>
</tr>
</table>
</form>
这里要注意的几点就是,第一行,必须有method=”post”和enctype=”multipart/form-data”,不然为默认使用get请求,最后就是提交这个表单了,请看下面的javascript片断:
dojo.io.iframe.send({ form: "form1", handleAs: "json", url: "ajax.jsp", handle: function(response, args) { alert(response.result) return response; } });
它的语法和dojo.xhrXXX的语法是相同的,但它不支持接受xml格式内容,在服务端返回的内容必须放到一个textarea标签里,例如:
response.getWriter().write(“<html><body><textarea>{result:\”出错\”}</textarea></body></html>”);
然后,我在客户端接收到返回的值后,进行处理:
var defer1 = new dojo.Deferred(); dojo.io.iframe.send({ form: "form1", handleAs: "json", url: "ajax.aspx", handle: function(response, args) { if (response.result == "ok") { defer1.callback(response) } else { defer1.errback(new Error(response.result)); alert(response.result) } return response; } });
这里又有一个新的东西了,叫dojo.Deferred,翻译过来就是“延迟处理”,因为很多时候,你不太可能把所有的代码都写在ajax返回方法,这个时候,就可以用到它了,好像jquery1.5之后才出现这个功能,有兴趣的可以了解下,这里我就不多说了,大家只需要知道它可以把方法引到外面来就行了,dojo的ajax里返回的也是它,然后我在下面写新的方法来显示刚才上传的图片:
defer1.addCallback(function(response) { var newNode = document.createElement("img"); dojo.attr(newNode, "src", response.imgUrl); dojo.place(newNode, dojo.query("body")[0], "last"); return response; })
这样写,它会在处理完提交后,按顺序自动调用这个方法。你只要一直return response;你就可以一直addCallback,有人叫这为”模拟进程”。
上一篇: Dojo基本DOM操作函数记录 下一篇: dojo widget生命周期及使用详解