浅谈Q的基本实现

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

GitHub Q的API

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

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() 返回值-> 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)
            }
          })
时间: 2024-08-02 17:28:55

浅谈Q的基本实现的相关文章

浅谈HTML5单页面架构(一)——requirejs + angular + angular-route

本文转载自:http://www.cnblogs.com/kenkofox/p/4643760.html 心血来潮,打算结合实际开发的经验,浅谈一下HTML5单页面App或网页的架构. 众所周知,现在移动Webapp越来越多,例如天猫.京东.国美这些都是很好的例子.而在Webapp中,又要数单页面架构体验最好,更像原生app.简单来说,单页面App不需要频繁切换网页,可以局部刷新,整个加载流畅度会好很多. 废话就不多说了,直接到正题吧,浅谈一下我自己理解的几种单页面架构: 1.requirejs

浅谈差分约束系统——图论不等式的变形

浅谈差分约束系统——图论不等式的变形 ----yangyaojia 版权声明:本篇随笔版权归作者YJSheep(www.cnblogs.com/yangyaojia)所有,转载请保留原地址! 一.定义 如若一个系统由n个变量和m个不等式组成,并且这m个不等式对应的系数矩阵中每一行有且仅有一个1和-1,其它的都为0,这样的系统称为差分约束( difference constraints )系统. 二.分析 简单来说就是给你n个变量,给m个形如x[i]-x[j]≥k①或x[i]-x[j]≤k②.求两

【ZOJ】3785 What day is that day? ——浅谈KMP应用之ACM竞赛中的暴力打表找规律

首先声明一下,这里的规律指的是循环,即找到最小循环周期.这么一说大家心里肯定有数了吧,“不就是next数组性质的应用嘛”. 先来看一道题 ZOJ 3785 What day is that day? Time Limit: 2 Seconds      Memory Limit: 65536 KB It's Saturday today, what day is it after 11 + 22 + 33 + ... + NN days? Input There are multiple tes

浅谈RPM

浅谈RPM [先絮叨下编译啊] 1. 库:其实就是一个程序模块(它没有执行入口,不能独立执行,只能被能独立运行的程序调用时执行)你可以把它想象成工具螺丝刀,可执行的程序是就是你自己:螺丝刀能自己干活吗?没有螺丝刀能拧螺丝吗?或者说你现在制作一个?螺丝刀可以实现这个功能但需要你来执行这个动作. 2.静态编译:将程序所需要的所有的库都编译进二进制程序,不依赖于共享库运行:就好像随身携带螺丝刀一样. 3.动态编译:程序所依赖的共享库并不会被编译进整个二进制程序,运行环境依赖于共享库:需要找到螺丝刀才能

Apache Spark源码走读之21 -- 浅谈mllib中线性回归的算法实现

欢迎转载,转载请注明出处,徽沪一郎. 概要 本文简要描述线性回归算法在Spark MLLib中的具体实现,涉及线性回归算法本身及线性回归并行处理的理论基础,然后对代码实现部分进行走读. 线性回归模型 机器学习算法是的主要目的是找到最能够对数据做出合理解释的模型,这个模型是假设函数,一步步的推导基本遵循这样的思路 假设函数 为了找到最好的假设函数,需要找到合理的评估标准,一般来说使用损失函数来做为评估标准 根据损失函数推出目标函数 现在问题转换成为如何找到目标函数的最优解,也就是目标函数的最优化

浅谈深度学习中潜藏的稀疏表达

浅谈深度学习中潜藏的稀疏表达 “王杨卢骆当时体,轻薄为文哂未休. 尔曹身与名俱灭,不废江河万古流.” — 唐 杜甫<戏为六绝句>(其二) [不要为我为啥放这首在开头,千人千面千理解吧] 深度学习:概述和一孔之见 深度学习(DL),或说深度神经网络(DNN), 作为传统机器学习中神经网络(NN).感知机(perceptron)模型的扩展延伸,正掀起铺天盖地的热潮.DNN火箭般的研究速度,在短短数年内带来了能“读懂”照片内容的图像识别系统,能和人对话到毫无PS痕迹的语音助手,能击败围棋世界冠军.引

浅谈内网渗透

引子离上篇文章的时间过去很久了,答应写一篇内网渗透的文章,今天抽点时间,把这个坑给添平了吧.标题是浅谈,所以我不认为自己能在内网渗透写的有多深入.渗透这玩意更多是经验,积累的多了自然水到渠成.而且我个人认为很多前辈人物都已经写的很好了,我这里纯粹抛砖引玉,把前辈级人物的经验集成在一起,也算基础篇吧.如果有不足的地方或者有更好的实现方法,欢迎随时交流.交流方式就以邮件吧,邮件地址在文章结束处,上次公开的Q加了很多人,即时通讯=即时打扰,过段时间集中清理,如果不小心被清理了,诸位勿怪,这里算是提前打

浅谈算法和数据结构: 四 快速排序

原文:浅谈算法和数据结构: 四 快速排序 上篇文章介绍了时间复杂度为O(nlgn)的合并排序,本篇文章介绍时间复杂度同样为O(nlgn)但是排序速度比合并排序更快的快速排序(Quick Sort). 快速排序是20世纪科技领域的十大算法之一 ,他由C. A. R. Hoare于1960年提出的一种划分交换排序. 快速排序也是一种采用分治法解决问题的一个典型应用.在很多编程语言中,对数组,列表进行的非稳定排序在内部实现中都使用的是快速排序.而且快速排序在面试中经常会遇到. 本文首先介绍快速排序的思

iOS开发之浅谈MVVM的架构设计与团队协作

今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦~). 由于本人项目经验有限,关于架构设计方面的东西理解有限,我个人对MVVM的理解主要是借鉴于之前的用过的MVC的Web框架~在学校的时候用过ThinkPHP框架,和SSH框架,都是MVC的架构模式,今天MVVM与传统的MVC可谓是极为相似,也可以说是兄弟关系,也就是一家人了. 说道架构设计和团队