博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
浅谈Q的基本实现
阅读量:2201 次
发布时间:2019-05-03

本文共 5208 字,大约阅读时间需要 17 分钟。

从整个的角度来说,Q的实现其实是闭包的一个应用,下文简单说明实现一下Q的基本功能。

GitHub Q的API

实现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的内容。

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的基本对象结构出来了。虽然没有实现。

then的实现

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/

你可能感兴趣的文章
Leetcode Go 《精选TOP面试题》20200628 69.x的平方根
查看>>
leetcode 130. Surrounded Regions
查看>>
【Python】详解Python多线程Selenium跨浏览器测试
查看>>
Jmeter之参数化
查看>>
Shell 和Python的区别。
查看>>
【JMeter】1.9上考试jmeter测试调试
查看>>
【虫师】【selenium】参数化
查看>>
【Python练习】文件引用用户名密码登录系统
查看>>
学习网站汇总
查看>>
【Python】用Python打开csv和xml文件
查看>>
【Loadrunner】性能测试报告实战
查看>>
【自动化测试】自动化测试需要了解的的一些事情。
查看>>
【selenium】selenium ide的安装过程
查看>>
【手机自动化测试】monkey测试
查看>>
【英语】软件开发常用英语词汇
查看>>
Fiddler 抓包工具总结
查看>>
【雅思】雅思需要购买和准备的学习资料
查看>>
【雅思】雅思写作作业(1)
查看>>
【雅思】【大作文】【审题作业】关于同不同意的审题作业(重点)
查看>>
【Loadrunner】通过loadrunner录制时候有事件但是白页无法出来登录页怎么办?
查看>>