• This repository has been archived on 23/Oct/2019
  • Stars
    star
    573
  • Rank 77,865 (Top 2 %)
  • Language
    JavaScript
  • Created about 11 years ago
  • Updated over 6 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

[快照]史上最快,与 node callback 完美结合的异步流程控制库!

then.js

史上最快,与 node callback 完美结合的异步流程控制库!

NPM version Build Status

能用简单优美的方式将任何同步或异步回调函数转换成then()链式调用!

你可以在服务器端(node.js)或浏览器中使用then.js,兼容ie6/7/8。

特征

  1. 可以像标准的 Promise 那样,把N多异步回调函数写成一个长长的 then 链,并且比 Promise 更简洁自然。因为如果使用标准 Promise 的 then 链,其中的异步函数都必须转换成 Promise,Thenjs 则无需转换,像使用 callback 一样执行异步函数即可。

  2. 可以像 async那样实现同步或异步队列函数,并且比 async 更方便。因为 async 的队列是一个个独立体,而 Thenjs 的队列在 Thenjs 链上,可形成链式调用。

  3. 强大的 Error 机制,可以捕捉任何同步或异步的异常错误,甚至是位于异步函数中的语法错误。并且捕捉的错误任君处置。

  4. 开启debug模式,可以把每一个then链运行结果输出到debug函数(未定义debug函数则用 console.log),方便调试。

Thunk

thunk 是一个被封装了同步或异步任务的函数,这个函数有唯一一个参数 callback。运行 **thunk**后,当其封装的任务执行完毕时,任务结果会输入 callback 执行。callback 的第一个参数是 error,没有发生 error 则为 null

推荐使用新一代异步流程控制库 thunks,它是比 co 更强大的存在!

##Benchmark

模拟异步测试:

➜  then.js git:(master) ✗ node --harmony benchmark/index
Async Benchmark...

JSBench Start (1000 cycles, async mode):
Test Promise...
Test co...
Test thunks-generator...
Test bluebird...
Test when...
Test RSVP...
Test async...
Test thenjs...
Test thunks...

JSBench Results:
co: 1000 cycles, 32.621 ms/cycle, 30.655 ops/sec
Promise: 1000 cycles, 30.807 ms/cycle, 32.460 ops/sec
when: 1000 cycles, 28.828 ms/cycle, 34.688 ops/sec
thunks: 1000 cycles, 17.402 ms/cycle, 57.465 ops/sec
RSVP: 1000 cycles, 10.358 ms/cycle, 96.544 ops/sec
thunks-generator: 1000 cycles, 9.822 ms/cycle, 101.812 ops/sec
bluebird: 1000 cycles, 8.54 ms/cycle, 117.096 ops/sec
async: 1000 cycles, 6.54 ms/cycle, 152.905 ops/sec
thenjs: 1000 cycles, 5.085 ms/cycle, 196.657 ops/sec

co: 100%; Promise: 105.89%; when: 113.16%; thunks: 187.46%; RSVP: 314.94%; thunks-generator: 332.12%; bluebird: 381.98%; async: 498.79%; thenjs: 641.51%;

JSBench Completed!

模拟异步测试:

➜  then.js git:(master) ✗ node --harmony benchmark/index
Sync Benchmark...

JSBench Start (1000 cycles, async mode):
Test Promise...
Test co...
Test thunks-generator...
Test bluebird...
Test when...
Test RSVP...
Test async...
Test thenjs...
Test thunks...

JSBench Results:
co: 1000 cycles, 26.342 ms/cycle, 37.962 ops/sec
Promise: 1000 cycles, 25.662 ms/cycle, 38.968 ops/sec
when: 1000 cycles, 21.36 ms/cycle, 46.816 ops/sec
thunks: 1000 cycles, 5.242 ms/cycle, 190.767 ops/sec
thunks-generator: 1000 cycles, 5.073 ms/cycle, 197.122 ops/sec
async: 1000 cycles, 2.806 ms/cycle, 356.379 ops/sec
RSVP: 1000 cycles, 2.27 ms/cycle, 440.529 ops/sec
bluebird: 1000 cycles, 1.722 ms/cycle, 580.720 ops/sec
thenjs: 1000 cycles, 1.324 ms/cycle, 755.287 ops/sec

co: 100%; Promise: 102.65%; when: 123.32%; thunks: 502.52%; thunks-generator: 519.26%; async: 938.77%; RSVP: 1160.44%; bluebird: 1529.73%; thenjs: 1989.58%;

JSBench Completed!

async 不支持过长(如超过3000)的同步任务(将会出现Maximum call stack size exceeded

Demo

'use strict';
/*global console*/

var Thenjs = require('../then.js');

function task(arg, callback) { // 模拟异步任务
  Thenjs.nextTick(function () {
    callback(null, arg);
  });
}

Thenjs(function (cont) {
  task(10, cont);
})
.then(function (cont, arg) {
  console.log(arg);
  cont(new Error('error!'), 123);
})
.fin(function (cont, error, result) {
  console.log(error, result);
  cont();
})
.each([0, 1, 2], function (cont, value) {
  task(value * 2, cont); // 并行执行队列任务,把队列 list 中的每一个值输入到 task 中运行
})
.then(function (cont, result) {
  console.log(result);
  cont();
})
.series([ // 串行执行队列任务
  function (cont) { task(88, cont); }, // 队列第一个是异步任务
  function (cont) { cont(null, 99); } // 第二个是同步任务
])
.then(function (cont, result) {
  console.log(result);
  cont(new Error('error!!'));
})
.fail(function (cont, error) { // 通常应该在链的最后放置一个 `fail` 方法收集异常
  console.log(error);
  console.log('DEMO END!');
});

Install

Node.js:

npm install thenjs

bower:

bower install thenjs

Browser:

<script src="/pathTo/then.js"></script>

API

以下所有的 'cont',取义于 continue。'cont' 绑定到了下一个 Thenjs 链,即收集当前任务结果,继续执行下一链。它等效于 node.js 的 callback,可以接受多个参数,其中第一个参数为 'error'。

Thenjs(start, [debug])

主构造函数,返回一个新的 Thenjs 对象。

  • start: Function,function (cont) {}, 即 thunk 函数(见下面解释),或者 Promise 对象,或者 Thenjs 对象,或者其他值。
  • debug: Boolean 或 Function,可选,开启调试模式,将每一个链的运行结果用 debug 函数处理,如果debug为非函数真值,则调用 console.log,下同
Thenjs().then(function(res) {});
Thenjs(123).then(function(res) {});
Thenjs(promise).then(function(res) {});
Thenjs(function(cont) { cont(result); }).then(function(res) {});

Thenjs.each(array, iterator, [debug])

array 中的值应用于 iterator 函数(同步或异步),并行执行。返回一个新的 Thenjs 对象。

  • array: Array 或 类数组
  • iterator: Function,function (cont, value, index, array) {}
Thenjs.each([0, 1, 2], function (cont, value) {
  task(value * 2, cont);
})
.then(function (cont, result) {
  console.log(result);
});

Thenjs.eachSeries(array, iterator, [debug])

array 中的值应用于 iterator 函数(同步或异步),串行执行。返回一个新的 Thenjs 对象。

  • array: Array 或 类数组
  • iterator: Function,function (cont, value, index, array) {}
Thenjs.eachSeries([0, 1, 2], function (cont, value) {
  task(value * 2, cont);
})
.then(function (cont, result) {
  console.log(result);
});

Thenjs.parallel(tasksArray, [debug])

tasksArray 是一个函数(同步或异步)数组,并行执行。返回一个新的 Thenjs 对象。

  • tasksArray: Array,[taskFn1, taskFn2, taskFn3, ...],其中,taskFn 形式为 function (cont) {}
Thenjs.parallel([
  function (cont) { task(88, cont); },
  function (cont) { cont(null, 99); }
])
.then(function (cont, result) {
  console.log(result);
});

Thenjs.series(tasksArray, [debug])

tasksArray 是一个函数(同步或异步)数组,串行执行。返回一个新的 Thenjs 对象。

  • tasksArray: Array,[taskFn1, taskFn2, taskFn3, ...],其中,taskFn 形式为 function (cont) {}
Thenjs.series([
  function (cont) { task(88, cont); },
  function (cont) { cont(null, 99); }
])
.then(function (cont, result) {
  console.log(result);
});
  • taskFn 形式为 function(cont,result){} 时,通过result可获取之前项的返回值
Thenjs.series([
  function (cont,result) { typeof result === 'undefined'; cont(null,100) },
  function (cont,result) { assert.equal(100,result[0]);cont(null, 99); },
  function (cont,result) { assert.equal(100,result[0]); assert.equal(99,result[1]);cont(null, 98); }
])
.then(function (cont, result) {
  console.log(result);
});

Thenjs.parallelLimit(tasksArray, limit, [debug])

tasksArray 是一个函数(同步或异步)数组,并行执行,最大并行数量为 limit,当并行队列中某一项完成时,会立即补上,也就是说,并发数会一直保持在 limit,除非待运行任务不足。返回一个新的 Thenjs 对象。

  • tasksArray: Array,[taskFn1, taskFn2, taskFn3, ...],其中,taskFn 形式为 function (cont) {}
  • limit: Number, 应该大于 0 的整数,取 0 则无限制
Thenjs.parallel([task1, task2, ..., taskN], 10)
.then(function (cont, result) {
  console.log(result);
});

Thenjs.eachLimit(array, iterator, limit, [debug])

类似于上,但将 array 中的值应用于 iterator 函数(同步或异步),并行执行,最大并行数量为 limit。返回一个新的 Thenjs 对象。

  • array: Array 或 类数组
  • iterator: Function,function (cont, value, index, array) {}
  • limit: Number, 应该大于 0 的整数,取 0 则无限制
Thenjs.eachLimit([1, 2, ..., n], function (cont, value) {
  task(value * 2, cont);
}, 10)
.then(function (cont, result) {
  console.log(result);
});

Thenjs.prototype.then(successHandler, [errorHandler])

如果上一链正确,则进入 successHandler 执行,否则进入 errorHandler 执行。返回一个新的 Thenjs 对象。

  • successHandler: Function,function (cont, value1, value2, ...) {}
  • errorHandler: Function,可选,function (cont, error) {}
Thenjs(function (cont) {
  task(10, cont);
})
.then(function (cont, arg) {
  console.log(arg);
}, function (cont, error) {
  console.error(error);
});

Thenjs.prototype.finally(finallyHandler)

别名:Thenjs.prototype.fin(finallyHandler)

原名all已停用。

无论上一链是否存在 error,均进入 finallyHandler 执行,等效于 .then(successHandler, errorHandler)。返回一个新的 Thenjs 对象。

  • finallyHandler: Function,function (cont, error, value1, value2, ...) {}

finallyHandler 也可以是外层的 cont 哦,如果是 cont, 则不会被注入本层的 cont, 所以,可以这样嵌套用:

Thenjs(function (cont) {
  task(10, cont);
})
.then(function (cont, arg) {
  console.log(arg);
  Thenjs(function (cont2) {
    task(10, cont2);
  })
  .then(function (cont2, arg) {
    console.log(arg);
    cont2(new Error('error!'), 123);
  })
  .fin(cont);
})
.fin(function (cont, error, result) {
  console.log(error, result);
  cont();
});

在复杂的异步组合中是很有用的。

Thenjs.prototype.fail(errorHandler)

别名:Thenjs.prototype.catch(errorHandler)

fail 用于捕捉 error,如果在它之前的任意一个链上产生了 error,并且未被 then, finally 等捕获,则会跳过中间链,直接进入 fail。返回一个新的 Thenjs 对象。

  • errorHandler: Function,function (cont, error) {}

类似 .finally(finallyHandler) ,这里的 errorHandler 也可以是 cont

Thenjs(function (cont) {
  task(10, cont);
})
.then(function (cont, arg) {
  console.log(arg);
  Thenjs(function (cont2) {
    task(10, cont2);
  })
  .then(function (cont2, arg) {
    console.log(arg);
    cont2(new Error('error!'), 123);
  })
  .fail(cont);
})
.then(function (cont, result) {
  console.log(result);
})
.fail(function (cont, error) {
  console.error(error);
});

Thenjs.prototype.each(array, iterator)

参数类似 Thenjs.each,返回一个新的 Thenjs 对象。

不同在于,参数可省略,如果没有参数,则会查找上一个链的输出结果作为参数,即上一个链可以这样 cont(null, array, iterator) 传输参数到each。下面三个队列方法行为类似。

Thenjs.prototype.eachSeries(array, iterator)

参数类似 Thenjs.eachSeries,返回一个新的 Thenjs 对象。

Thenjs.prototype.parallel(tasksArray)

参数类似 Thenjs.parallel,返回一个新的 Thenjs 对象。

Thenjs.prototype.series(tasksArray)

参数类似 Thenjs.series,返回一个新的 Thenjs 对象。

Thenjs.prototype.parallelLimit(tasksArray, limit)

参数类似 Thenjs.parallelLimit,返回一个新的 Thenjs 对象。

Thenjs.prototype.eachLimit(array, iterator, limit)

参数类似 Thenjs.eachLimit,返回一个新的 Thenjs 对象。

Thenjs.prototype.toThunk()(callback)

返回 thunk 函数。将 Thenjs 对象变成一个 thunk, 当 Thenjs 对象任务执行完毕后,结果会进入 callback 执行。callback 的第一个参数仍然是 error

var thunk = Thenjs(function (cont) {
  task(10, cont);
})
.then(function (cont, arg) {
  console.log(arg);
  Thenjs(function (cont2) {
    task(10, cont2);
  })
  .then(function (cont2, arg) {
    console.log(arg);
    cont2(new Error('error!'), 123);
  })
  .fail(cont);
})
.then(function (cont, result) {
  console.log(result);
})
.toThunk();

thunk(function (error, result) {
  console.log(error, result);
});

Thenjs.nextTick(callback, arg1, arg2, ...)

工具函数,类似于 node.jssetImmediate,异步执行 callback,而 arg1, arg2 会成为它的运行参数。

Thenjs.defer(errorHandler, callback, arg1, arg2, ...)

工具函数,类似于 Thenjs.nextTick,不同的是异步使用 try catch 执行 callback,如果捕捉到 error,则进入 errorHandler 执行。

  • errorHandler: Function,function (error) {}

Thenjs.onerror = function (error) {};

全局配置参数,用户可自定义的全局 error 监听函数,Thenjs.onerror 默认值为 undefined。若定义,当执行链上发生 error 且没有被捕捉时,error 会进入 Thenjs.onerror

Who Used

Examples

更多使用案例请参考jsGen源代码!

More Repositories

1

gear

A lightweight, composable and high performance web service framework for Go.
Go
551
star
2

teambition-sdk

Isomorphic JavaScript SDK for Teambition APIs
TypeScript
433
star
3

rrule-go

Go library for working with recurrence rules for calendar dates.
Go
313
star
4

TBEmptyDataSet

An extension of UITableView/UICollectionView's super class, it will display a placeholder emptyDataSet when the data of tableView/collectionView is empty.
Swift
206
star
5

Hire

Working With Great People
200
star
6

gulp-sequence

Run a series of gulp tasks in order
JavaScript
195
star
7

gulp-ssh

SSH and SFTP tasks for gulp
JavaScript
183
star
8

merge2

Merge multiple streams into one stream in sequence or parallel (~119M/month downloads).
JavaScript
171
star
9

DropdownMenu

Dropdown menu for NavigationController in Swift, also support Dropup Menu
Swift
133
star
10

snapper-core

Teambition push messaging service, backed by redis.
JavaScript
115
star
11

webapp-solutions

Try to collect anwsers on problems we encounter in Web Apps
113
star
12

ReactiveDB

Reactive ORM for Lovefield
TypeScript
105
star
13

jsonrpc-lite

Parse and Serialize JSON-RPC2 messages in node.js, or browser.
JavaScript
95
star
14

ratelimiter-go

The fastest abstract rate limiter, base on go-redis/redis.
Go
93
star
15

RRuleSwift

Swift rrule library for working with recurrence rules of calendar dates.
JavaScript
90
star
16

swaggo

Convert Go annotations to Swagger Documentation (version 2.0)
Go
68
star
17

SegmentedControl

A highly customizable segmented control for iOS applications.
Swift
64
star
18

HanziPinyin

A lightweight Swift library supporting convertion between Chinese(both Simplified and Tranditional) characters and Pinyin.
Swift
57
star
19

WebBrowser

A web browser using WebKit and written in Swift for iOS apps.
Swift
55
star
20

timed-queue

Distributed timed job queue, backed by Redis.
JavaScript
50
star
21

pdfviewer

PDF Viewer using Mozilla PDF JS
JavaScript
49
star
22

AMRAudioSwift

A useful tool to encode or decode audio between AMR and WAVE.
Swift
38
star
23

CardStyleTableView

An extension of UITableView and UITableViewCell which displays a card style view in grouped tableView, similar to the system's tableView before iOS 7.
Swift
32
star
24

trie-mux

A minimal and powerful trie based url path router (or mux) for Go.
Go
27
star
25

Pocket-Node-SDK

Headless Node.js SDK for integrating with [Pocket](http://getpocket.com/)
CoffeeScript
23
star
26

TB-Icons

A classified icons set that consists of a part of Material Design icons and some original icons by TB-UI team. Available in Icon Fonts and SVG Symbols.
Stylus
23
star
27

limbo

Factory/Loader of mongoose
CoffeeScript
17
star
28

json-mask-go

👺 JSON mask for Go
Go
10
star
29

tb-i18n-loader

i18n loader of teambition web for webpack
JavaScript
9
star
30

tws-auth

Node.js SDK of TWS (Teambition Web Service) client.
TypeScript
8
star
31

snapper-swift

Snapper-core client by Swift 2.0
Swift
8
star
32

node-teambition

JavaScript
7
star
33

redlimit

RedLimit is a redis-based distributed rate limit HTTP service, implemented with Rust.
Rust
7
star
34

tb-apps-sdk

Teambition API Bridge
TypeScript
7
star
35

teambition-node-sdk

teambition node sdk for server applications
TypeScript
6
star
36

WeChatSDK

Swift version of WeChat SDK.
Objective-C
5
star
37

node-chinese-finance-number

JavaScript
4
star
38

smart-limiter

Smart rate limiter middleware for express.
JavaScript
4
star
39

urbs-setting

Urbs 灰度平台灰度策略服务
Go
4
star
40

ilog

light-weight, smart and pure log module
JavaScript
3
star
41

teambition-java-sdk

teambition java sdk for server applications
Java
3
star
42

pipe-errors

Handle errors on piping streams and pipe error to the end.
JavaScript
3
star
43

i18n-middleware

An i18n middleware built for web apps.
CoffeeScript
2
star
44

grpclb

grpclb policy that consistent hash implemention, base on discovery systems like etcd, consul etc.
Go
2
star
45

teambition-server-sdk

TypeScript
2
star
46

gem-next

general entity manager next generation
TypeScript
2
star
47

tws-tcm

Node.js SDK of TWS (Teambition Web Service) cloud messaging service
TypeScript
1
star