实现nodejs的promises库(基于promise.js改写)

时间:2022-10-22 12:57:20

原promise.js库地址:https://github.com/stackp/promisejs

promises是JavaScript实现优雅编程的一个非常不错的轻量级框架。该框架可以让你从杂乱的多重异步回调代码中解脱出来,并把精力集中到你的业务逻辑上。

今天从GIT源码库中下载了promise.js,发现该源码是基于Web前端JavaScript写的,并不能直接用于nodejs。还好代码不是很多,也不是很复杂。经过分析整合,将其实现为nodejs的一个框架,代码如下:

(function(){
/**
* Copyright 2012-2013 (c) Pierre Duquesne <stackp@online.fr>
* script: promise.js
* description: promises的nodejs模块
* modified: https://github.com/stackp/promisejs
* authors: alwu007@sina.cn
* */

var Promise = exports.Promise = function(){
    this._callbacks = [];
};

Promise.prototype.then = function(func, context){
    //处理回调结果的方法
    function doCallbackResults(r) {
        if (r instanceof Promise) {
            r.then(function(err, values){
                p.done(err, values);
            });
        } else {
            p.done(null, r);
        }
    }

var p = new Promise();
    if (this._isdone) {
        var results = func.apply(context, this.results);
        doCallbackResults(results);
    } else {
        this._callbacks.push(function(){
            var results = func.apply(context, arguments);
            doCallbackResults(results);
        });
    }
    return p;
};

Promise.prototype.done = function(){
    this.results = arguments;
    this._isdone = true;
    for (var i=0; i<this._callbacks.length; i++) {
        this._callbacks[i].apply(null, arguments);
    }
    this._callbacks = [];
};

Promise.join = function(promises){
    var p = new Promise();
    var results = [];

if (!promises || !promises.length) {
        p.done(results);
        return p;
    }

var numdone = 0;
    var total = promises.length;

function notifier(i) {
        return function() {
            numdone += 1;
            results[i] = Array.prototype.slice.call(arguments);
            if (numdone === total) {
                p.done(results);
            }
        };
    }

for (var i = 0; i < total; i++) {
        promises[i].then(notifier(i));
    }

return p;
};

Promise.chain = function(funcs, args) {
    var p = new Promise();
    if (!funcs || !funcs.length) {
        p.done.apply(p, args);
    } else {
        funcs[0].apply(null, args).then(function(){
            funcs.splice(0, 1);
            Promise.chain(funcs, arguments).then(function(){
                p.done.apply(p, arguments);
            });
        });
    }
    return p;
};
})();

另附测试代码如下:

/**
* script: test.js
* description: promise.js测试代码
* */

var promise = require('./mypromise');

function asyncfoo() {
    var p = new promise.Promise();
    setTimeout(function(){
        p.done();
    }, 1000);
    return p;
}

function syncfoo() {
    var p = new promise.Promise();
    p.done();
    return p;
}

var o = {};
/*
asyncfoo().then(function(){
    return 'Raymond';
}, o).then(function(err, name){
    o.name = name;
    return asyncfoo().then(asyncfoo).then(function(){
        return asyncfoo().then(asyncfoo).then(function(){
            return 18;
        });
    });
}, o).then(function(err, age){
    o.age = age;
    return asyncfoo().then(asyncfoo).then(function(){
        return asyncfoo().then(asyncfoo).then(function(){
            return 'boy';
        });
    }).then(function(err, sex){
        return sex;
    });
}).then(function(err, sex){
    o.sex = sex;
    return 'Hello, world!';
}).then(function(err, say){
    o.say = say;
    console.dir(o);
});

syncfoo().then(function(){
    return 'Raymond';
}, o).then(function(err, name){
    o.name = name;
    return syncfoo().then(syncfoo).then(function(){
        return syncfoo().then(syncfoo).then(function(){
            return 18;
        });
    });
}, o).then(function(err, age){
    o.age = age;
    return asyncfoo().then(asyncfoo).then(function(){
        return asyncfoo().then(asyncfoo).then(function(){
            return 'boy';
        });
    }).then(function(err, sex){
        return sex;
    });
}).then(function(err, sex){
    o.sex = sex;
    return 'Hello, world!';
}).then(function(err, say){
    o.say = say;
    console.dir(o);
});
*/
function asyncfoo1(){
    var p = new promise.Promise();
    setTimeout(function(){
        p.done(null, 'Raymond');
    }, 1000);
    return p;
}

function asyncfoo2(err, name){
    o.name = name;
    var p = new promise.Promise();
    setTimeout(function(){
        p.done(null, 18);
    }, 1000);
    return p;
}
function asyncfoo3(err, age){
    o.age = age;
    var p = new promise.Promise();
    setTimeout(function(){
        p.done(null, 'boy');
    }, 1000);
    return p;
}
function asyncfoo4(){
    var p = new promise.Promise();
    setTimeout(function(){
        p.done(null, 'Hello, world!');
    }, 1000);
    return p;
}
promise.Promise.chain([asyncfoo1, asyncfoo2, asyncfoo3]).then(function(err, sex){
    o.sex = sex;
    return asyncfoo4();
}).then(function(err, say){
    o.say = say;
}).then(function(){
    console.dir(o);
});

实现nodejs的promises库(基于promise.js改写)的更多相关文章

  1. &lbrack;译&rsqb;基于Vue&period;js的10个最佳UI框架,用于构建移动应用程序

    原文查看10 Best Vue.js based UI Frameworks for Building Mobile Apps 如果您期待使用Vue.js构建移动应用程序,那么您可以选择许多可用的UI ...

  2. queue-fun —— nodejs下基于Promise的队列控制模块。

    工作告一段落,闲来无事,写了一个在nodejs实现“半阻塞”的控制程序. 一直以来,nodejs以单线程非阻塞,高并发的特性而闻名.搞这个“半阻塞”是东西,有什么用呢? 场景一: 现在的web应用可有 ...

  3. axios - 基于 Promise 的 HTTP 异步请求库

    axios 是基于 Promise 的 HTTP 请求客户端,可同时在浏览器和 node.js 中使用.Vue 更新到2.0之后,作者就宣告不再对 vue-resource 模块更新,而是推荐使用 a ...

  4. Axios 是一个基于 promise 的 HTTP 库

    Axios 是一个基于 promise 的 HTTP 库 vue项目中关于axios的简单使用 axios介绍 Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.j ...

  5. 基于promise用于浏览器和node&period;js的http客户端的axios

    axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征: 从浏览器中创建 XMLHttpRequest 从 node.js 发出 http 请求 支 ...

  6. RSuite 一个基于 React&period;js 的 Web 组件库

    RSuite http://rsuite.github.io RSuite 是一个基于 React.js 开发的 Web 组件库,参考 Bootstrap 设计,提供其中常用组件,支持响应式布局. 我 ...

  7. 【360开源】thinkjs:基于Promise的Node&period;js MVC框架 (转)

    thinkjs是360奇舞团开源的一款Node.js MVC框架,该框架底层基于Promise来实现,很好的解决了Node.js里异步回调的问题.360奇舞团(奇虎75Team),是奇虎360公司We ...

  8. Vue项目中使用基于Vue&period;js的移动组件库cube-ui

    cube-ui 是滴滴公司的技术团队基于 Vue.js 实现的精致移动端组件库.很赞,基本场景是够用了,感谢开源!感谢默默奉献的你们. 刚爬完坑,就来总结啦!!希望对需要的朋友有小小的帮助. (一)创 ...

  9. KoaHub平台基于Node&period;js开发的Koa 连接支付宝插件代码信息详情

    KoaHub平台基于Node.js开发的Koa 链接支付宝插件代码信息详情 easy-alipay alipay payment & notification APIs easy-alipay ...

随机推荐

  1. C&num;&plus;JQuery&plus;&period;Ashx&plus;百度Echarts实现全国省市地图和饼状图动态数据图形报表的统计

    在目前的一个项目中,需要用到报表表现数据,这些数据有多个维度,需要同时表现出来,同时可能会有大量数据呈现的需求,经过几轮挑选,最终选择了百度的echarts作为报表基础类库.echarts功能强大,界 ...

  2. 在PHP中无法连接Memcached的解决办法

    Memcached 已经正确安装配置, 并且防火墙也已经打开了本机对自己所有端口的访问, telnet localhost 11211也正常, 但是通过PHP访问出现 [Sat May 17 22:0 ...

  3. 转载:node&period;js socket&period;io

    本文转自:http://www.xiaocai.name/post/cf1f9_7b6507  学习node.js socket.io 使用 用node.js(socket.io)实现数据实时推送 在 ...

  4. shell脚本实例-游戏脚本

    http://bbs.chinaunix.net/thread-3580033-1-1.html shell游戏收集贴 #!/bin/bash # Tetris Game #APP declarati ...

  5. newusers和chpasswd

    一.为什么需要大批量添加用户: 我们什么时候才需要大批量添加用户呢?有时我们需要让几十个或更多的用户在主机上完成相同或相似的任务,比如我们想同时添加一堆的ftp 用户,这些ftp用户归属同一组,但不允 ...

  6. Windows下使用cmd启动Oracle EM和sql命令使用&plus;主机身份认证

    (1)cmd命令下使用sql命令 >sqlplus / as sysdba sql>select * from v$version; (2)cmd命令下启动Oracle EM 安装完ora ...

  7. EL四大作用域 9个jsp对象有效范围 及 对应的类

    java中request,session,application的作用范围 page,request,session,application四者的作用范围: page的作用范围是当前页面:对应El表达 ...

  8. 使用FFMPEG在windows平台下推rtmp流

    使用FFMPEG在windows平台下推rtmp流 工作中习惯在Linux下面使用FFmpeg模拟推rtmp流,无奈家中的电脑都是windows系统,需要利用家中的带宽来测试流媒体服务器的性能.所以研 ...

  9. LeetCode--No&period;012 Integer to Roman

    12. Integer to Roman Total Accepted: 71315 Total Submissions: 176625 Difficulty: Medium Given an int ...

  10. 《剑指offer》-数据流中的中位数

    如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值. 最开始的思路 ...