原文:http://dojotoolkit.org/documentation/tutorials/1.10/ajax/难度等级:初级 Dojo 版本:1.10

起步

dojo/request 允许你无需刷新页面就可以向 server 发送或接收数据(也就是大家熟知的 AJAX)。本章介绍的新特性可以使编写的代码更紧凑,执行的更快速。本章内容涉及 dojo/promise 和 dojo/Deferred,这些模块被 dojo/request 用来进行异步编程。本章不能涵盖所有内容,但请记住 promises 和 Deferreds可以让编写非阻塞异步代码更为简单。本章之后,你再学习更多教程。

dojo/request 介绍

先看个简单例子:

require(["dojo/request"], function(request){

request("helloworld.txt").then(

function(text){

console.log("The file's content is: " + text);

},

function(error){

console.log("An error occurred: " + error);

}

);

});

在浏览器中,以上代码会使用 XMLHttpRequest 发出一个HTTP GET 请求,获取 helloworld.txt ,并且返回一个。如果请求成功,then() 当中的第一个 function 会执行,文件的文本内容是其唯一参数;如果请求失败,then() 当中的第二个 function 会执行,参数是一个 error 对象。如果我们需要发送表单数据到 server 该怎么做?响应的数据为 JSON 或 XML 又该如何处理?都没问题 -- dojo/request API 允许定制 request。The dojo/request API

每次 request 都需要一样东西:对端 (end-point)。因此,dojo/request 的第一个参数就是请求的URL 。

web 开发者希望他们的工具足够灵活,可以按应用要求或不同的环境进行调整。dojo/request API 可以很好的达到这个要求:dojo/request 的第一个必选的参数是请求的 URL。第二个参数使用一个  object 来定制请求。其中最有用的选项是:

method - 大写的字符串,指明发出 request 时 HTTP 的方法类型。有几个辅助函数可以简化操作(request.get,request.post, request.put, request.del).

sync -  boolean 值,如果为 true,则阻塞 request ,直到 server 响应或等待超时。

query - 字符串,或一个包含键值对的 object,用于追加查询参数到 URL 。

data - 字符串,或一个包含键值对的 object,或 FormData object,用于包含需要传给 server 的数据 。

timeout - 设定超时值(毫秒),并设定异常处理句柄。

handleAs - 字符串,用来指定如何转换响应返回的有效数据,转换后送入回调函数( success handler)。可用的格式有: "text" (缺省), "json", "javascript", 和 "xml"。

headers - 用来设置随 request 一起发送的额外的头部信息。

我们来看一个具体例子:

require(["dojo/request"], function(request){

request.post("post-content.php", {

data: {

color: "blue",

answer: 42

},

headers: {

"X-Something": "A value"

}

}).then(function(text){

console.log("The server returned: ", text);

});

});

这个例子发送一个 HTTP POST 到 post-content.php;将一个简单的对象 (data那部分) 串行化并作为 POST 数据随 request 一起发送,同时附带"X-Something" 头部信息。server 响应后,返回的有效数据将传入request.post 生成的 promise 中。例子: request.get 和request.post

下面是 dojo/request 的一些常见用法。

在页面中显示一个文本文件的内容

这个例子使用 dojo/request.get 请求一个 text 文件。这种设计一般用于提供某种静态信息如服务器环境、配置信息等,因为服务器只是响应请求,将文件发送到本地(译注:言下之意,你没法修改它),很ming在服务端维护个静态文本比维护代码要简单。

译注:由于嵌入代码包含 html 块级标签 ,显示不大正常,统一在标签前面加“!”,原始代码请参考原文。

require(["dojo/dom", "dojo/on", "dojo/request", "dojo/domReady!"],

function(dom, on, request){

// Results will be displayed in resultDiv

var resultDiv = dom.byId("resultDiv");

// 给 textButton 绑定onclick 事件句柄

on(dom.byId("textButton"), "click", function(evt){

// Request the text file

request.get("../resources/text/psalm_of_life.txt").then(

function(response){

// 显示文本文件内容

resultDiv.innerHTML = ""+response+"";

},

function(error){

// 显示错误信息

resultDiv.innerHTML = "error\">"+error+"";

}

);

});

}

);

View Demo

登录演示

下面这个例子,用 POST 请求将用户名和密码发送到 server,然后显示 server 返回结果。

require(["dojo/dom", "dojo/on", "dojo/request", "dojo/dom-form"],

function(dom, on, request, domForm){

var form = dom.byId('formNode');

// 关联表单的 onsubmit 事件句柄

on(form, "submit", function(evt){

// prevent the page from navigating after submit

evt.stopPropagation();

evt.preventDefault();

// Post 数据到 server

request.post("../resources/php/login-demo.php", {

// 发送用户名和密码

data: domForm.toObject("formNode"),

// 设定2秒响应超时

timeout: 2000

}).then(function(response){

dom.byId('svrMessage').innerHTML = response;

});

});

}

);

View Demo

Headers 演示

下面这个例子,同上个例子一样使用 POST 请求,增加了一个 Auth-Token 头部的访问。(注:Auth-Token 似乎同安全有关,可以防止 cookie 被复制盗用)

为访问头部信息,我们使用原生 Promise 的 promise.response.getHeader 方法 (从 XHR 返回的 Promise 没有这个属性)。另外,使用 promise.response.then,response 就不再是简单的 data,而是一个包含 data 属性的对象。

require(["dojo/dom", "dojo/on", "dojo/request", "dojo/dom-form"],

function(dom, on, request, domForm){

// 结果会显示在 resultDiv 中

var form = dom.byId('formNode');

// 关联表单的onsubmit 事件句柄

on(form, "submit", function(evt){

// prevent the page from navigating after submit

evt.stopPropagation();

evt.preventDefault();

// Post 数据到server

var promise = request.post("../resources/php/login-demo.php", {

// 发送用户名和密码

data: domForm.toObject("formNode"),

// 设定2秒响应超时

timeout: 2000

});

// 不再使用 promise.then ,而是使用 promise.response.then

promise.response.then(function(response){

// 从 data 属性获取信息

var message = response.data;

// 访问 'Auth-Token' 头部信息

var token = response.getHeader('Auth-Token');

dom.byId('svrMessage').innerHTML = message;

dom.byId('svrToken').innerHTML = token;

});

});

}

);

View Demo

JSON (JavaScript Object Notation)

在 AJAX 请求中 是一种非常通用的数据编码方式,因为它易于阅读,便于操作,格式紧凑。JSON 可以编码(encode)任何类型的数据:很多语言都包含或支持 JSON 格式,如  , , , , , 和 。

JSON encoded object

{

"title":"JSON Sample Data",

"items":[{

"name":"text",

"value":"text data"

},{

"name":"integer",

"value":100

},{

"name":"float",

"value":5.65

},{

"name":"boolean",

"value":false

}]

}

如果把 handleAs 设置为 "json", dojo/request 会将 response 的有效数据作为 JSON 数据进行解码,转换成 JavaScript 对象。

译注:由于嵌入代码包含 html 块级标签 ,显示不大正常,统一在标签前面加“!”,原始代码请参考原文。

require(["dojo/dom", "dojo/request", "dojo/json",

"dojo/_base/array", "dojo/domReady!"],

function(dom, request, JSON, arrayUtil){

// Results will be displayed in resultDiv

var resultDiv = dom.byId("resultDiv");

// Request the JSON data from the server

request.get("../resources/data/sample.json.php", {

// Parse data from JSON to a JavaScript object

handleAs: "json"

}).then(function(data){

// Display the data sent from the server

var html = "

JSON Data" +

"JSON encoded data:" +

"" + JSON.stringify(data) + ""+

"

Accessing the JSON data" +

"title " + data.title + "" +

"items An array of items." +

"Each item has a name and a value. The type of " +

"the value is shown in parentheses.";

arrayUtil.forEach(data.items, function(item,i){

html += "" + item.name +

"" + item.value +

" (" + (typeof item.value) + ")";

});

html += "";

resultDiv.innerHTML = html;

},

function(error){

// Display the error returned

resultDiv.innerHTML = error;

});

}

);

In addition to the encoding the data as JSON in the response, set the  header to application/json, either using server configuration such as  or adding it to the header with the server side code.

View Demo

JSONP (Javascript Object Notation with Padding)

AJAX 请求不能跨域。需要跨域的话,可以使用 。使用 JSONP时,一个 script 标签会被插入到当前页面中, the src file is requested, 服务端会将数据包裹在一个回调函数中,当 response 被解析时, the callback is called with the data as its first argument. 可以使用   发出 JSONP 请求。

看些例子吧:

使用 JSONP 从服务端请求数据,并处理响应

require(["dojo/dom", "dojo/on", "dojo/request/script",

"dojo/json", "dojo/domReady!"

], function(dom, on, script, JSON){

// 结果会显示在 resultDiv 中

var resultDiv = dom.byId("resultDiv");

// 给 makeRequest 绑定 onclick 事件句柄

on(dom.byId('makeRequest'),"click", function(evt){

// 按钮点击后,以 JSONP 请求形式发送本地日期、时间到 server

var d = new Date(),

dateNow = d.toString();

script.get("../resources/php/jsonp-demo.php",{

// Tell the server that the callback name to

// use is in the "callback" query parameter

jsonp: "callback",

// 发送日期、时间

query: {

clienttime: dateNow

}

}).then(function(data){

// 显示结果

resultDiv.innerHTML = JSON.stringify(data);

});

});

});

因为 response 是 JavaScript 代码,不是 JSON 数据,所以response 中的 Content-Type header 应该是 application/javascript。

View Demo

Using JSONP to request Dojo pull requests from the GitHub API

require(["dojo/dom", "dojo/on", "dojo/request/script",

"dojo/dom-construct", "dojo/_base/array",

"dojo/domReady!"

], function(dom, on, script, domConstruct, arrayUtil){

var pullsNode = dom.byId("pullrequests");

// 给 tweetButton 关联 onclick 事件句柄

on(dom.byId("pullrequestsButton"), "click", function(evt){

// 向 Dojo's GitHub repo的开放 pull 接口发起请求

script.get("", {

// 通过 "callback" query 参数告诉 GitHub服务器,用来包裹数据的函数名称是什么

jsonp: "callback"

}).then(function(response){

// 清空 tweets 节点

domConstruct.empty(pullsNode);

// Create a document fragment to keep from

//doing live DOM manipulation

var fragment = document.createDocumentFragment();

// 遍历每一个 pull 请求,为每一项创建一个列表项

arrayUtil.forEach(response.data, function(pull){

var li = domConstruct.create("li", {}, fragment);

var link = domConstruct.create("a", {href: pull.url, innerHTML: pull.title}, li);

});

// 将文档片段加入到列表中

domConstruct.place(fragment, pullsNode);

});

});

});

View Demo

Reporting Status

提供了一种机制,用于报告 dojo/request 提交的请求的状态 (也可是 dojo/request 中任何其他 provider)。加载 dojo/request/notify 模块就可以允许 providers 发射事件,我们就可以监听事件,据此汇报请求状态。要监听一个事件,需要给加载 dojo/request/notify 模块后的句柄传递两个参数:事件名称和监听函数( listener function)。下面是 dojo/request providers 可发射的事件:

支持的 dojo/request/notify 事件

start - 当请求第一次发送出去时发射

send - Emitted prior to a provider sending a request

load - 当 provider 收到响应成功的 response 时发射

error - 当 provider 收到错误时发射

done - 当 provider 完成 request 时发射,无论请求成功与否

stop - 当所有的在途 requests 都结束时发射

"start" 和 "stop" 上的 listener 无需参数。"send" 上的 listener 接收两个参数: 一个代表 request  的对象和一个注销函数。调用注销函数就会在 request开始前将其取消。"load", "error", 和 "done" 的 listener 接收一个参数:一个代表服务端 response 的对象。我们来看一个实例:

使用 dojo/request/notify 监控 requests 进度

译注:由于嵌入代码包含 html 块级标签 ,显示不大正常,统一在标签前面加“!”,原始代码请参考原文。

require(["dojo/dom", "dojo/request", "dojo/request/notify",

"dojo/on", "dojo/dom-construct", "dojo/query",

"dojo/domReady!"],

function(dom, request, notify, on, domConstruct){

// Listen for events from request providers

notify("start", function(){

domConstruct.place("Start","divStatus");

});

notify("send", function(data, cancel){

domConstruct.place("Sent request","divStatus");

});

notify("load", function(data){

domConstruct.place("Load (response received)","divStatus");

});

notify("error", function(error){

domConstruct.place("Error","divStatus");

});

notify("done", function(data){

domConstruct.place("Done (response processed)","divStatus");

if(data instanceof Error){

domConstruct.place("Error","divStatus");

}else{

domConstruct.place("Success","divStatus");

}

});

notify("stop", function(){

domConstruct.place("Stop","divStatus");

domConstruct.place("Ready", "divStatus");

});

// Use event delegation to only listen for clicks that

// come from nodes with a class of "action"

on(dom.byId("buttonContainer"), ".action:click", function(evt){

domConstruct.empty("divStatus");

request.get("../resources/php/notify-demo.php", {

query: {

success: this.id === "successBtn"

},

handleAs: "json"

});

});

}

);

dojo/request/registry

provides a mechanism to route requests based on the URL requested. Common uses of the registry are to assign a provider based on whether the request will be made to the current domain using JSON, or to a different domain using JSONP. You may also use this approach if the URLs can vary based on the operations in progress.

dojo/request/registry 语法

request.register(url, provider, first);

dojo/request/registry 参数

url - url 是一个字符串,正则表达式(regEx),或者函数。

string - 如果 url 是字符串,则在 url 完全匹配后provider 将启用。

regExp - 如果 url 是正则表达式,则在请求的URL 匹配后 provider 将启用。

function - 如果 url 是个函数,URL 以及 request 附带的选项 object 会传给函数。当函数执行返回 true 时,provider 将启用。

provider -  指定用来处理 request 请求的 provider

first - 一个可选参数,为 boolean 值。如果为真,在已注册的 providers 前注册这个 provider(译注:有优先级吗?)。

看一个最终的例子:

使用 dojo/request/registry ,基于请求的 URL ,关联 provider

译注:由于嵌入代码包含 html 块级标签 ,显示不大正常,统一在标签前面加“!”,原始代码请参考原文。require(["dojo/request/registry", "dojo/request/script", "dojo/dom",

"dojo/dom-construct", "dojo/on", "dojo/domReady!"],

function(request, script, dom, domConstuct, on){

// 将所有访问 "http://" 的请求注册到 script provider

// 而对本地资源的访问将使用 xhr

request.register(/^https?:\/\//i, script);

// When the search button is clicked

on(dom.byId("searchButton"), "click", function(){

// First send a request to twitter for all tweets

// tagged with the search string

request("", {

query: {

q:"#" + dom.byId("searchText").value,

result_type:"mixed",

lang:"en"

},

jsonp: "callback"

}).then(function(data){

// 如果 tweets 节点已存在了,销毁它

if (dom.byId("tweets")){

domConstuct.destroy("tweets");

}

// 如果至少有一个返回结果

if (data.results.length > 0) {

// 创建一个新的 tweet 列表

domConstuct.create("ul", {id: "tweets"},"twitterDiv");

// 将每一个 tweet 添加成一个 li

while (data.results.length>0){

domConstuct.create("li", {innerHTML: data.results.shift().text},"tweets");

}

}else{

// 如果没有结果返回

domConstuct.create("p", {id:"tweets",innerHTML:"None"},"twitterDiv");

}

});

// 接下来发送一个本地检索的 request

request("../resources/php/search.php", {

query: {

q: dom.byId("searchText").value

},

handleAs: "json"

}).then(

function(data){

dom.byId('localResourceDiv').innerHTML =

"" + data.name + "" +

},

function(error){

// 如果没有搜索结果,本地搜索会返回一个 404

dom.byId('localResourceDiv').innerHTML = "None";

}

);

});

}

);

最佳实践

使用 dojo/request 的最佳实践:

仔细选择 request 方式method。GET通常用于简单的非安全性数据获取。Get一般比 POST 快。POST通常用于发送难以通过 URL 传递的表单数据 。

对需要保护的数据或者 HTTPS 页面使用 HTTPS 。

AJAX 请求不需刷新页面,因此大多数人都会做一个状态提示,显示 加载... 直到完成。

为更好地检测及恢复 request 错误,要使用错误回调。

使用有效的开发工具可以更快的解决问题。

尽可能多用几种浏览器仔细测试你的代码。

小结

dojo/request 提供了一个跨浏览器兼容的 AJAX 接口,可以实现本地以及跨域请求,有设计良好的错误处理,支持信息通告,支持基于 URL 的 request 路由分发。dojo/request 调用的返回值是个 promise,运行批量发出 requests 然后异步处理 responses。页面内容可以包括多个数据源,每个数据源请求完成后数据立即可用。快使用 dojo/request 加速你的页面吧!

其他资源

ajax dojo deferred,Dojo学习-14:Ajax with dojo/request相关推荐

  1. .net ajax 怎么写,.NET学习篇--Ajax中Url的写法

    .NET学习篇--Ajax中Url的写法 什么是Ajax AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML). AJAX 不是新的 ...

  2. dojo异步编程之dojo/Deferred

    dojo/Deferred介绍 dojo/Deferred是一个类,是Dojo中管理异步线程的基础. 简单来说,一个Deferred对象会等待一段时间再去执行指定的调用,直到某个特定的事件发生或者前一 ...

  3. ajax dojo deferred,dojo(四):ajax请求

    储备知识 1.在介绍新版本的ajax请求之前,需要先了解一些dojo/Deferreds. 初次听到"Deferred"这个概念,可能会觉得这是一个神秘的东西.实际上它在执行异步操 ...

  4. mvc中ajax的跳转,springmvc ajax 跳转的学习笔记

    Spring Web MVC是什么 Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,下面我们来看一篇关于springmvc ajax 跳转 ...

  5. Java Script 学习笔记 -- Ajax

    AJAX 一 AJAX预备知识:json进阶 1.1 什么是JSON? JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.JSON是用字符串来表示Javas ...

  6. Django开发学习之Ajax(二)

    Ajax准备知识:json 什么是json? 定义: JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式. 它基于 ECMAScript ( ...

  7. telerik grid ajax,Telerik ajax 控件学习笔记 - Ajax

    产品版本:RadControls for ASP.NET Ajax Q1 2009 Telerik 的控件实现 Ajax 的方式比 asp.net ajax 要简单些.有如下特点: 1. 不需要拖放很 ...

  8. dojo学习之2——使用 Dojo 掌握面向对象开发

    使用 Dojo 模拟基于类的 OOP 在深入讨论 Dojo 的基于类的模拟之前,重要的是要注意到,到目前为止,Dojo 仍然是一个 JavaScript 库.Java 代码和 JavaScript 不 ...

  9. jquery deferred ajax,Ajax的deferred实现

    模拟ajax的 script请求 模拟jQuery.ajax的script请求 /** * 模拟ajax的 script请求 * @param {[type]} options [descriptio ...

  10. 前端一定得学ajax吗,前端学习之ajax

    一.什么是json JSON(JavaScriptObjectNotation,JS对象标记)是一种轻量级的数据交换格式. 它基于ECMAScript(w3c制定的js规范)的一个子集,采用完全独立于 ...

最新文章

  1. jQuery插件simplePagination的使用-踩坑记_03
  2. 高通平台MSM8916LCM模块移植(一)-bootloader部分
  3. 程序员十大非技术面试问题及策略
  4. 这位数字艺术的开拓者,通过计算机算法成就了新的艺术表达方式
  5. python 蒙特卡罗_蒙特卡洛模拟(Python)深入教程
  6. 从Demo到Engine(二) -- Render Queue Sort
  7. 中公电网计算机类题库讲练版百度云,2021电网二批招聘考试题库:计算机类练习题(5)...
  8. 为什么我的Linux主机内存用的那么快?
  9. 怎样利用php记录时间差,使用PHP计算出时间差的实现方法
  10. JDK 安装 Java环境变量配置 详细教程
  11. 关于RH850系统时钟初始化的分析解读
  12. 面试软件测试的时候,应届生怎么包装自己的简历?
  13. 微信小程序转码机器人
  14. 怎么把图片转换成pdf格式?图片转PDF方法
  15. C#WinFormRS232串口工具
  16. 计算机存储单位 t后面的单位,字节后面的存储单位是什么
  17. bzoj1529: [POI2005]ska Piggy banks
  18. dd命令生成随机大小的二进制文件
  19. Ubuntu系统---FeiQ安装记录
  20. 深度学习在基因组学中的应用

热门文章

  1. 探索YoloV3源码
  2. OSChina 周四乱弹 ——来,带你吃旋转寿司
  3. 对bootstrop中左右浮动设置
  4. 日志收集系统Flume笔记(基础版)
  5. 大胖子走迷宫 [蓝桥杯 ]
  6. python抓取豆瓣电影
  7. CT图像的窗宽窗位(VTK及3Dslicer中的使用)
  8. 自我调整【管理学之十三】
  9. 文本溢出隐藏显示...和英文换行
  10. 【渝粤教育】电大中专中药炮制学作业 题库