A small and magical composer for all JavaScript asynchronous.
ES3+, support node.js and all browsers.
thunk
是一个被封装了同步或异步任务的函数;
thunk
有唯一一个参数 callback
,是 CPS 函数;
thunk
运行后返回新的 thunk
函数,形成链式调用;
thunk
自身执行完毕后,结果进入 callback
运行;
callback
的返回值如果是 thunk
函数,则等该 thunk
执行完毕将结果输入新 thunk
函数运行;如果是其它值,则当做正确结果进入新的 thunk
函数运行;
var thunk = require('../thunks.js')()
var fs = require('fs')
var size = thunk.thunkify(fs.stat)
// generator
thunk(function *() {
// sequential
console.log(yield size('.gitignore'))
console.log(yield size('thunks.js'))
console.log(yield size('package.json'))
})(function *(error, res) {
//parallel
console.log(yield [
size('.gitignore'),
size('thunks.js'),
size('package.json')
])
})()
var thunk = require('../thunks.js')()
var fs = require('fs')
var size = thunk.thunkify(fs.stat)
// sequential
size('.gitignore')(function (error, res) {
console.log(error, res)
return size('thunks.js')
})(function (error, res) {
console.log(error, res)
return size('package.json')
})(function (error, res) {
console.log(error, res)
})
// parallel
thunk.all([
size('.gitignore'),
size('thunks.js'),
size('package.json')
])(function (error, res) {
console.log(error, res)
})
// sequential
thunk.seq([
size('.gitignore'),
size('thunks.js'),
size('package.json')
])(function (error, res) {
console.log(error, res)
})
Node.js:
npm install thunks
bower:
bower install thunks
Browser:
<script src="/pathTo/thunks.js"></script>
var thunks = require('thunks')
母函数,生成一个带作用域的 thunk
生成器,作用域是指该 thunk
生成器直接或间接生成的所有子 thunk 函数的内部运行环境。
thunk
,任何异常会输入到下一个子 thunk 函数:var thunk = thunks()
onerror
监听的 thunk
,该 thunk
作用域内的任何异常都可被 onerror
捕捉,而不会进入下一个 子 thunk 函数,除非 onerror
返回 true
:var thunk = thunks(function (error) { console.error(error) })
onerror
监听,onstop
监听和 debug
监听的 thunk
,onerror
同上,该 thunk
作用域内的所有运行结果都会先进入 debug
函数,然后再进入下一个子 thunk 函数:var thunk = thunks({
onstop: function (sig) { console.log(sig) },
onerror: function (error) { console.error(error) },
debug: function () { console.log.apply(console, arguments) }
})
拥有不同作用域的多个 thunk
生成器组合成复杂逻辑体时,各自的作用域仍然相互隔离,也就是说 onerror
监听和 debug
监听不会在其它作用域运行。
生成器,生成一个新的子 thunk 函数。
其中 thunkable
可以是:
var thunk1 = thunk(1)
var thunk2 = thunk(thunk1) // thunk2 等效于 thunk1
thunk(function (callback) {
callback(null, 1)
})(function (error, value) {
console.log(error, value) // null 1
})
var promise = Promise.resolve(1)
thunk(promise)(function (error, value) {
console.log(error, value) // null 1
})
toThunk
方法的对象var then = Thenjs(1) // then.toThunk() 能转换成 thunk 形式的函数,也能用于 `co`
thunk(then)(function (error, value) {
console.log(error, value) // null 1
})
co
类似,但更进一步,可以 yield
任何值,可以形成链式调用thunk(function *() {
var x = yield 10
return 2 * x
})(function *(error, res) {
console.log(error, res) // null, 20
return yield [1, 2, thunk(3)]
})(function *(error, res) {
console.log(error, res) // null, [1, 2, 3]
return yield {
name: 'test',
value: thunk(1)
}
})(function (error, res) {
console.log(error, res) // null, {name: 'test', value: 1}
})
thunk(1)(function (error, value) {
console.log(error, value) // null 1
})
thunk([1, 2, 3])(function (error, value) {
console.log(error, value) // null [1, 2, 3]
})
还可以这样运行(this):
thunk.call({x: 123}, 456)(function (error, value) {
console.log(error, this.x, value) // null 123 456
return 'thunk!'
})(function (error, value) {
console.log(error, this.x, value) // null 123 'thunk!'
})
返回一个新的子 thunk 函数。
obj
是一个包含多个子 thunk 函数或 promise 的数组或对象,并发执行各个子 thunk 函数,全部执行完毕后其结果形成一个新数组(顺序与原数组对应)或对象,输入到返回的新子 thunk 函数。
thunk.all([
thunk(0),
thunk(1),
2,
thunk(function (callback) { callback(null, [3]) })
])(function (error, value) {
console.log(error, value) // null [0, 1, 2, [3]]
})
thunk.all({
a: thunk(0),
b: thunk(1),
c: 2,
d: thunk(function (callback) { callback(null, [3]) })
})(function (error, value) {
console.log(error, value) // null {a: 0, b: 1, c: 2, d: [3]}
})
还可以这样运行(this):
thunk.all.call({x: [1, 2, 3]}, [4, 5, 6])(function (error, value) {
console.log(error, this.x, value) // null [1, 2, 3] [4, 5, 6]
return 'thunk!'
})(function (error, value) {
console.log(error, this.x, value) // null [1, 2, 3] 'thunk!'
})
返回一个新的子 thunk 函数。
thunkX
可以是任何值,thunk.seq
会按照顺序将其转换子 thunk 函数 并逐步执行,全部执行完毕后其结果形成一个新数组(顺序与原数组对应),输入到返回的新子 thunk 函数。
thunk.seq([
function (callback) {
setTimeout(function () {
callback(null, 'a', 'b')
}, 100)
},
thunk(function (callback) {
callback(null, 'c')
}),
[thunk('d'), thunk('e')], // thunk in array will be excuted in parallel
function (callback) {
should(flag).be.eql([true, true])
flag[2] = true
callback(null, 'f')
}
])(function (error, value) {
console.log(error, value) // null [['a', 'b'], 'c', ['d', 'e'], 'f']
})
or
thunk.seq(
function (callback) {
setTimeout(function () {
callback(null, 'a', 'b')
}, 100)
},
thunk(function (callback) {
callback(null, 'c')
}),
[thunk('d'), thunk('e')], // thunk in array will be excuted in parallel
function (callback) {
should(flag).be.eql([true, true])
flag[2] = true
callback(null, 'f')
}
)(function (error, value) {
console.log(error, value) // null [['a', 'b'], 'c', ['d', 'e'], 'f']
})
还可以这样运行(this):
thunk.seq.call({x: [1, 2, 3]}, 4, 5, 6)(function (error, value) {
console.log(error, this.x, value) // null [1, 2, 3] [4, 5, 6]
return 'thunk!'
})(function (error, value) {
console.log(error, this.x, value) // null [1, 2, 3] 'thunk!'
})
返回一个新的子 thunk 函数。迭代数组所有子 thunk 函数最先完成的运算结果会传入其中,无论正确或错误。
返回一个新的子 thunk 函数。
将 nodejs callback 风格的输入值转换成一个新的子 thunk 函数,该子 thunk 函数的结果值为 (error, val1, val2, ...)
,即直接将 digest
的参数传入到新的子 thunk 函数,相当于:
thunk(function (callback) {
callback(error, val1, val2, ...)
})
使用场景:
thunk(function (callback) {
//...
callback(error, result)
})(function (error, value) {
//...
return thunk.digest(error, value)
})(function (error, value) {
//...
})
还可以这样运行(this):
var a = {x: 1}
thunk.digest.call(a, null, 1, 2)(function (error, value1, value2) {
console.log(this, error, value1, value2) // { x: 1 } null 1 2
})
返回一个新函数,运行该函数会返回子 thunk 函数。
将带 callback 参数的 nodejs 风格的函数 fn
转换成一个新的函数,新函数不再接收 callback
,其输出为子 thunk 函数。
var thunk = require('../thunks.js')()
var fs = require('fs')
var fsStat = thunk.thunkify(fs.stat)
fsStat('thunks.js')(function (error, result) {
console.log('thunks.js: ', result)
})
fsStat('.gitignore')(function (error, result) {
console.log('.gitignore: ', result)
})
还可以这样运行(this):
var obj = {a: 8}
function run (x, callback) {
//...
callback(null, this.a * x)
}
var run = thunk.thunkify.call(obj, run)
run(1)(function (error, result) {
console.log('run 1: ', result)
})
run(2)(function (error, result) {
console.log('run 2: ', result)
})
lift
概念来自于 Haskell,它将一个同步函数转化成一个异步函数。该异步函数接受 thunkable
参数,等所有参数求得真实值后,再按照原函数逻辑运行。该异步函数返回子 thunk 函数。
var thunk = require('../thunks.js')()
function calculator (a, b, c) {
return (a + b + c) * 10
}
var calculatorT = thunk.lift(calculator)
var value1 = thunk(2)
var value2 = Promise.resolve(3)
calculatorT(value1, value2, 5)(function (error, result) {
console.log(result) // 100
})
You may also write code with this
:
var calculatorT = thunk.lift.call(context, calculator)
将 thunkable
值转换成一个可以持久化的 thunk 函数,可以无限次运行该函数而取得其值。
var thunk = require('../thunks.js')()
var persistThunk = thunk.persist(thunk(x))
persistThunk(function (error, result) {
console.log(1, result) // x
return persistThunk(function (error, result) {
console.log(2, result) // x
return persistThunk
})
})(function (error, result) {
console.log(3, result) // x
})
You may also write code with this
:
var persistThunk = thunk.persist.call(context, thunkable)
返回一个新的子 thunk 函数,该子 thunk 函数的主体将会在 delay
毫秒之后运行。
console.log('thunk.delay 500: ', Date.now())
thunk.delay(500)(function () {
console.log('thunk.delay 1000: ', Date.now())
return thunk.delay(1000)
})(function () {
console.log('thunk.delay end: ', Date.now())
})
还可以这样运行(this):
console.log('thunk.delay start: ', Date.now())
thunk.delay.call(this, 1000)(function () {
console.log('thunk.delay end: ', Date.now())
})
终止 thunk
函数组合体的运行,类似于 Promise
的 cancelable
(ES6 没有定义,原生 Promise 也未实现)。运行 thunk.stop
将抛出一个终止信号对象。终止信号能被作用域的 onstop
捕获,但也能被 try catch
捕获并屏蔽。
终止信号拥有 message
、特殊的 code
和 status === 19
(POSIX signal SIGSTOP)。
var thunk = require('thunks')({
debug: function (res) {
if (res) console.log(res) // { [Error: Stop now!] code: {}, status: 19 }
}
})
thunk(function (callback) {
thunk.stop('Stop now!')
console.log('It will not be run!')
})(function (error, value) {
console.log('It will not be run!')
})
thunk.delay(100)(function () {
console.log('Hello')
return thunk.delay(100)(function () {
thunk.stop('Stop now!')
console.log('It will not be run!')
})
})(function (error, value) {
console.log('It will not be run!')
})
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
1. 开源生态
2. 协作、人、软件
3. 评估模型