原文:http://blog.csdn.net/lovelyelfpop/article/details/51282675
英文原文:Asynchronous JavaScript: Promises
JavaScript 是单线程的, 代码自顶向下执行. 所以两段代码不能同时执行. 比如, 你可能从外部服务器下载一个 JSON 文件, 你就必须等待, 直到文件下载完毕. 为了不阻塞线程, 可以使用异步 JavaScript 来简化代码的执行.
你可能已经熟悉了异步 JavaScript. 事件(观察者模式observer pattern) 和 回调(Callbacks) 就是异步代码的两个例子. 比如, 不管你什么时候发起一个 Ext.Ajax 请求或者点击一个按钮,这个动作都会被加入一个队列中,这个被称作 事件循环(event loop)。JavaScript引擎不会处理事件循环,直到异步函数(自顶向下)之后的代码被调用. 这意味着 JavaScript 代码不是多线程的,尽管它看起来像是.
事件循环(Event Loop)
回调函数(Callbacks)通常用在当你有一个异步操作的时候(比如,从数据库加载数据),用来通知调用者异步操作完成了. 当调用这样的函数的时候,可以把另一个函数当做参数传给它。回调里面嵌套回调,是一个 不错的解决方案,我认为这是 JavaScript 的强大的功能之一。不过,当你的代码需要其他异步代码块的时候,就会很混乱.
比如,你从本地存储(local storage)中读取用户设置(这是callback #1)。基于这些设置,你用一个数据库连接来向外部服务器发起一个请求,(这是callback #2). 在显示结果在屏幕上之前,你还从数据库中获得其他内容(这是callback #3).
当你创建一个大型企业应用的时候,这些步骤很常见。在你的代码中,会出现回调函数里写了另一个回调函数,然后又在另一个回调函数中。你可以想想一下,如果这些函数分布在不同的文件中,一个月后再来回过头读这些代码是多么痛苦.
这时,JavaScript Promises 就派上用场了. 这是一种新的书写方式,可以让代码更加容易阅读和理解。Promise 代表任务的结果, 不管结果是否完成. 就像获取值的一个合同,我们可能并不知道 promise 何时被创建. Promise 是一个对象或者一个函数,带着一个 then 方法. 因为有这个“then”方法,动作就可以无穷无尽的链接在后面, 非常酷.
Promise 通常有4个状态.
完成(fulfilled) – promise 成功的时候
驳回(rejected) – promise 失败的时候
待定(pending) – 进行中, 未完成(fulfilled)也未驳回(rejected)
已定(settled) – 要么已经完成(fulfilled),要么已经驳回(rejected)
Promises 是 ECMAScript 6 的一部分,已经在某些现代浏览器中支持了,在最新的 Node.js 中也支持。下面的浏览器不支持 JavaScript Promises: Explorer 11 或更低版本, Android 4.4 或更低版本, 和 iOS Safari 7.1 或更低版本.
Ext JS 6 支持 Promises,符合 Promises A+ 规范; Classic 和 Modern toolkits 都支持它. 你可以调用 Sencha Promises 类, 它是对原生 JavaScript 功能的封装. 传统浏览器会使用 Sencha 提供的向后支持, 现代浏览器则使用原生功能.
这是例子是一个函数,返回一个 Sencha Promise 对象:
requestUserSettings: function(){ return new Ext.Promise(function (resolve, reject) { //一些异步操作, 比如加载一个 store Ext.getStore(‘Settings’).load({ callback: function(records, operation, success) { if(success){ if(records.length > 0){ //成功 resolve(records); } else { //成功,但是没有结果 resolve(false); } } else{ //失败 reject(operation); } } }); }); }
Ext.Promise 构造函数接收一个参数 - 一个带有2个参数的回调, resolve 和 reject. 当异步地做了某些事情之后, 比如从本地存储的 store 中获得了用户设置, 在 callback 里面,如果一切正常,它会调用 “resolve”,参数就是结果, 否则调用 “reject”,参数就是错误信息.
下面是使用 Promise 的例子:
this.requestUserSettings().then(function(records) { //成功. 利用 records 做其他事情 }, function(err) { //发生异常, 显示友好的错误信息 });
“then” 接收2个额参数,一个成功回调,一个失败回调。两个参数都是可选的,所以你可以只传递一个成功回调或者失败回调。你可以在后面链接任意多个 then 函数,来执行其它的异步操作.
除了 “then()” 函数, 还有终止 Promise 链的函数 (“done()”), 取消 待定(pending) 链 (“cancel()”). 还有, 可以为 Promise 链 附加一个 onCompleted 回调 (“always()”), 比如不管结果是什么都执行某些清理的逻辑. 同样的, 如果链里的某一个动作被驳回(rejected), 可以附加一个 onRejected 回调 (“otherwise()”), 例如处理失败逻辑.
除了 Ext.Promise, Sencha 也将推出 Ext.Deferred, 这是 Ext JS 6 里用来创建 Promises 的一种机制. 这两个的区别是, 在 deferred 构造函数中,创建者可以直接访问“幕后”的东西, 比如进度更新.
最后但并非最不重要的, Sencha 为 Ext.Ajax 集成了 Promises 支持.
Ext.Ajax.request() 现在是一个继承自 Ext.data.request.Base 类的实例, 它可以支持跟一个 then 函数. 允许你编写如下代码:
Ext.Ajax.request({ url: 'feed.json', }).then(function(response) { // 使用 response }).always(function() { // 清理的逻辑, 不管结果 }).otherwise(function(reason){ // 处理失败 });
还有很多更多的信息,解释如何使用 JavaScript 和 ExtJS 的 Promises。看看这些资源,以了解更多!
处理异步 JavaScript: 事件, 回调 & Promises/Deferreds (presentation)
Ext JS API 文档
Ext.Promise
Ext.promise.Promise-method-then
Ext.Deferred
Promises 规范
Mozilla Promise 规范
欢迎加入Sencha Touch + Phonegap交流群
1群:194182999 (满)
2群:419834979
共同学习交流(博主QQ:479858761)