约战Angular中Promise(1)
来源:互联网 发布:如何隐藏mac下方菜单 编辑:程序博客网 时间:2024/04/20 00:10
在angular出现之前,web开发中前端跟后台的交互采用xhr的ajax技术,即xhr的异步请求,异步肯定就不能阻塞当前的线程,所以这个时候回调就非常重要,在commonJS中曾定义过promise规范,即一个异步请求函数把一个耗时操作请求提交出去,可以马上获得返回值,这个返回值就是传说中的promise,说到promise,有一个很重要的方法就是then()方法,这个方法一般会有两个参数,分别为resolve,reject,这两个一般为function对象,作为完成时的回调方法,要实现回调,事件机制是非常有必要的,在nodeJS中,是底层基于event Loop的事件轮询实现可怕的io回调金字塔,所以在angular中,就让异步轮询队列(就是AsyncQueue)来在ng中来担任这个重要角色。
ng中promise的实现主要靠一个$q
服务,这个service由$QProvider
的$get()
构造,这个函数主要调用qFactory函数对Q进行构造,q服务是ng实现promise的一个关键服务,首先它有一个重要的方法defer(),这是个含有多个闭包的方法,主要是构造一个promise发生器(我暂时这么称呼它),里面含有resolve(),reject(),还有多出来的一个notify()工具方法,这些方法都是未来的then()回调方法,最重要的是,这个defered对象还有一个promise的对象属性,所谓的then()就定义在promise里面了,我们先来看看promise里面的then方法:
then: function(callback, errback, progressback) { var result = defer(); var wrappedCallback = function(value) { try { result.resolve((isFunction(callback) ? callback : defaultCallback)(value)); } catch(e) { result.reject(e); exceptionHandler(e); } }; var wrappedErrback = function(reason) { try { result.resolve((isFunction(errback) ? errback : defaultErrback)(reason)); } catch(e) { result.reject(e); exceptionHandler(e); } }; var wrappedProgressback = function(progress) { try { result.notify((isFunction(progressback) ? progressback : defaultCallback)(progress)); } catch(e) { exceptionHandler(e); } }; if (pending) { pending.push([wrappedCallback, wrappedErrback, wrappedProgressback]); } else { value.then(wrappedCallback, wrappedErrback, wrappedProgressback); } return result.promise; }, "catch": function(callback) { return this.then(null, callback); }
在这段代码中我们直接看then()方法其实就定义了三个方法,wrappedCallback (),wrappedErrback (),wrappedProgressback (),其实这三个方法都是对应resolve(),reject(),notify()三个方法,这三个方法主要的任务就是对我们then()里面的三个参数(在ng中有个神奇的地方就是不仅有成功和错误的回调处理,还可以触发notify事件,监听任务处理的进度)进行判断(比如是否为function对象),鉴于三个函数有异曲同工之妙,我就只来分析第一个就好了,首先在then()的开始,通过defer()构造出来一个defe对象
var result = defer();
因为要调用这个对象的三个处理方法,所以需要得到一个defer对象,然后then()需要检查当前回调的情况,即查看pending的值,如果当前回调金字塔还没有结束,即当前回调的结果还是一个promise,即链式的then()调用(在nodeJS等中经常使用的回调金字塔转换为then()调用链),然后then()就把三个传进来的参数(这三个参数就是我们用户自定义的各种情形处理的回调函数),进行封装,然后把它们push进等待队列进行等候,如下:
if (pending) { pending.push([wrappedCallback, wrappedErrback, wrappedProgressback]); } else { value.then(wrappedCallback, wrappedErrback, wrappedProgressback); } return result.promise;
可以看到最后then()return回来的还是一个promise类型,这就为then()的链式调用提供结构基础。
然而then()这么给我们定义的三个回调做这么一层封装到底有什么作用呢,看看在封装中then()主要干了什么:
try { result.resolve((isFunction(callback) ? callback : defaultCallback)(value)); } catch(e) { result.reject(e); exceptionHandler(e); } };
上面的result就是实现通过defer()构造的对象,可以看到,如果这个封装的回调方法被执行到,就会借用defer对象的一个工具方法resolve(),这个函数主要的作用就是成功时对我们函数执行结果进行分析(里面可以看到我们的Callback已经被调用了),下面进入这个函数代码:
resolve: function(val) { if (pending) { var callbacks = pending; pending = undefined; value = ref(val); if (callbacks.length) { nextTick(function() { var callback; for (var i = 0, ii = callbacks.length; i < ii; i++) { callback = callbacks[i]; value.then(callback[0], callback[1], callback[2]); } }); } } }
首先是一个判断,如果当前回调链已经空了,即不是一个pending状态,就说明then()已经执行到尽头了,本次处理到此就可以收工,如果还在pending状态,那么就开始取then()调用链的下一个元素了,这里就有一个比较复杂的地方了,就是涉及到then()调用链的变化以及关联的等待队列的一个变化,以及nextTick()函数调用道德ng内部的事件轮询机制,我们先且看下回详细分解。。。
- 约战Angular中Promise(1)
- 约战Angular中Promise(2)
- Angular(五)Promise
- 在Angular中使用promise
- angular promise
- angular中的$q与promise(综合)
- 了解Promise Angular(转)
- angular $q,defer,promise
- Javascript异步流程控制之Promise(1)-Angular $q简介
- Angular的 $q, defer, promise
- ES6中promise(摘自吕大豹大话讲解Promise)
- 无约无期的等待(1)
- angular 异步处理模式promise---$q
- 浅谈Angular的 $q, defer, promise
- Angular的 $q, defer, promise,$http
- 浅谈Angular的 $http, $q, defer, promise
- Angular通信$q服务和promise对象
- js中Promise详解(转)
- HDU - 2602 Bone Collector(01背包)
- POJ 2752 后缀数组
- UVa 10892 - LCM Cardinality
- [Python]对List进行复制时需要注意的问题
- 边框和background-背景设置
- 约战Angular中Promise(1)
- 递归,回溯,合并,动态规划算法笔记
- 程序员编程艺术:第七章、求连续子数组的最大和
- 程序员编程艺术第三十二~三十三章:最小操作数,木块砌墙问题
- RMQ问题
- 算法之LCA与RMQ问题
- 最长公共子序列(LCS)问题
- *LeetCode-Populating Next Right Pointers in Each Node
- eetCode] Basic Calculator & Basic Calculator II Basic Calculator