标签:闭包 q javascript
从整个的角度来说,Q的实现其实是闭包的一个应用,下文简单说明实现一下Q的基本功能。
实现Q的功能,先了解一下Q的API
通过 https://github.com/kriskowal/q 截取最简单那部分的文档如下:
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() 返回值-> promiss
add().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)
}).then(function(data){
throw new Error()
}).catch(function(err){
if(err){
console.log("There is a Error!")
console.log(err)
}
})
标签:闭包 q javascript
原文地址:http://blog.csdn.net/a6383277/article/details/44211895