本文共 5208 字,大约阅读时间需要 17 分钟。
从整个的角度来说,Q的实现其实是闭包的一个应用,下文简单说明实现一下Q的基本功能。
实现Q的功能,先了解一下Q的API
通过 截取最简单那部分的文档如下:
var deferred = Q.defer();FS.readFile("foo.txt", "utf-8", function (error, text) { if (error) { deferred.reject(new Error(error)); } else { deferred.resolve(text); }});return deferred.promise;
可以看到关键的api 有 defer
, reject
, promiss
, resolve
,然后文档还涉及到结果的取值,和错误捕捉,包括then
, catch
, done
, 就不再贴出来。
首先 从前四个api开始。 通过第一行代码
var deferred = Q.defer();
那么可明显得出的代码是:
var Q = { defer: function(){ }}
然后defer()
的返回值deffred
拥有3个属性。
var Q = { defer: function(){ return { reject: function(error){ }, resolve: function(data){ }, promiss: null //当前还不能确定是个什么值 } }}
以上基本的代码结构出来了。在来补充promiss的内容。
问来方便说明,这里先预设一个使用环境。从结果来推导代码实现。
var add = function(){ var deferred = Q.defer() setTimeout(function(){ deferred.resolve(2) }, 2000) return deferred.promise } add().then(function(data){ console.log(data) return data + 1 }).then(function(data){ console.log(data) }).then(function(data){ throw new Error() }).catch(function(err){ if(err){ console.log("There is a Error!") console.log(err) } })
可以看到上面的add就使用了Q. 先看
add().then(...).then(...).catch(...)
那么可以明确,deffred.promiss
至少有三个属性 (then,catch两个加上没有出现的done),并且其中的两个应该返回的是原对象。所以得到
var Q = { defer: function(){ var promiss = { then: function(fn){ //接收回调函数做为参数 // ... do something return promiss }, catch: function(fn){ //... do something return promss }, done: function(){} } return { reject: function(error){}, resolve: function(data){}, promiss: promiss } }}
如此以上,整个Q的基本对象结构出来了。虽然没有实现。
var add = function(){ var deferred = Q.defer() setTimeout(function(){ deferred.resolve(2) }, 2000) return deferred.promise }
通过上述代码发现, 计算结果是异步的存储的,那么当结果计算完成后,then里面的函数应该执行。如下
var Q = { defer: function(){ var promiss = { then: function(fn){ //接收回调函数做为参数 // ... do something return promiss //将自身对象返回很容易做到链式调用 }, ... } return { promiss: promiss ... } }}
所以
add() 返回值-> promissadd().then() 返回值-> promiss
接着来看 数据的传递。异步后resolve函数得到调用,获取到了实际结果,这个实际的返回值需要给then里面的回调函数。这个无法通过直接调用then来实现数据传递的。因此需要一个中间处理函数。如下:
var Q = { defer: function(){ //定义一个结果处理函数。 var callResult = function(data){ //do some thing }; var promiss = { then: function(fn){ //接收回调函数做为参数 // ... do something return promiss //将自身对象返回很容易做到链式调用 }, ... } return { resolve: function(data){ callResult(data) } ... } }}
做到这里关键点来了,需要解决的问题有两个, 1.怎么在resolve 函数调用时,把结果传给then的回调,并且让它执行? 2.then的返回值怎么需要给下一个then?
闭包的实现就在这里了。闭包的主要作用就是隔离作用域,以及向上层上下文寻找变量。
解决关键,使用个队列 来 存储所then的所有回调,在resolve执行时,执行这个队列里面的所有函数,并且把返回值循环赋值。
下面是完整的代码。var Q = { defer: function(){ 'use strict' //正常结果集 var resultQueue = []; //错误处理句柄 var errorHandle = function(error){ }; var promise = { then: function(fn){ //存储每一个then的回调函数,进行统一处理 resultQueue.push(fn) return promise }, done: function(){ return { catch: promise.catch } }, catch: function(fn){ errorHandle = fn } } var callAllResultQueue = function(data){ for(var i = 0; i < resultQueue.length; i++){ data = resultQueue[i](data); } } return { resolve: function(data){ //resolve触发所有then回调函数的执行。 callAllResultQueue(data) }, reject: function(error){ errorHandle(error) } promise: promise } } } var add = function(){ var deferred = Q.defer() setTimeout(function(){ deferred.resolve(2) }, 2000) return deferred.promise } add().then(function(data){ console.log(data) return data + 1 }).then(function(data){ console.log(data) }).catch(function(err){ if(err){ console.log("There is a Error!") console.log(err) } })
转载地址:http://njgub.baihongyu.com/