[Sencha ExtJS] 异步 JavaScript: Promises

原文:http://blog.csdn.net/lovelyelfpop/article/details/51282675



英文原文:Asynchronous JavaScript: Promises


JavaScript 是单线程的, 代码自顶向下执行. 所以两段代码不能同时执行. 比如, 你可能从外部服务器下载一个 JSON 文件, 你就必须等待, 直到文件下载完毕. 为了不阻塞线程, 可以使用异步 JavaScript 来简化代码的执行.


你可能已经熟悉了异步 JavaScript. 事件(观察者模式observer pattern) 和 回调(Callbacks) 就是异步代码的两个例子. 比如, 不管你什么时候发起一个 Ext.Ajax 请求或者点击一个按钮,这个动作都会被加入一个队列中,这个被称作 事件循环(event loop)。JavaScript引擎不会处理事件循环,直到异步函数(自顶向下)之后的代码被调用. 这意味着 JavaScript 代码不是多线程的,尽管它看起来像是.


[Sencha ExtJS] 异步 JavaScript: Promises_第1张图片

事件循环(Event Loop)



回调函数(Callbacks)通常用在当你有一个异步操作的时候(比如,从数据库加载数据),用来通知调用者异步操作完成了. 当调用这样的函数的时候,可以把另一个函数当做参数传给它。回调里面嵌套回调,是一个 不错的解决方案,我认为这是 JavaScript 的强大的功能之一。不过,当你的代码需要其他异步代码块的时候,就会很混乱.



比如,你从本地存储(local storage)中读取用户设置(这是callback #1)。基于这些设置,你用一个数据库连接来向外部服务器发起一个请求,(这是callback #2). 在显示结果在屏幕上之前,你还从数据库中获得其他内容(这是callback #3).



当你创建一个大型企业应用的时候,这些步骤很常见。在你的代码中,会出现回调函数里写了另一个回调函数,然后又在另一个回调函数中。你可以想想一下,如果这些函数分布在不同的文件中,一个月后再来回过头读这些代码是多么痛苦.


这时,JavaScript Promises 就派上用场了. 这是一种新的书写方式,可以让代码更加容易阅读和理解。Promise 代表任务的结果, 不管结果是否完成. 就像获取值的一个合同,我们可能并不知道 promise 何时被创建. Promise 是一个对象或者一个函数,带着一个 then 方法. 因为有这个“then”方法,动作就可以无穷无尽的链接在后面, 非常酷.


Promise 通常有4个状态.

  1. 完成(fulfilled) – promise 成功的时候

  2. 驳回(rejected) – promise 失败的时候

  3. 待定(pending) – 进行中, 未完成(fulfilled)也未驳回(rejected)

  4. 已定(settled) – 要么已经完成(fulfilled),要么已经驳回(rejected)

[Sencha ExtJS] 异步 JavaScript: Promises_第2张图片


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)


你可能感兴趣的:(ExtJs,promises)