Thunks
A small and magical composer for all JavaScript asynchronous.
Install / Use
/learn @thunks/ThunksREADME
thunks
A small and magical composer for all JavaScript asynchronous.
[![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![js-standard-style][js-standard-image]][js-standard-url] [![Coverage Status][coveralls-image]][coveralls-url] [![Downloads][downloads-image]][downloads-url]
Compatibility
ES5+, support node.js and browsers.
Summary
- thunks
- Compatibility
- Summary
- Implementations
- What is a thunk
- Demo
- Installation
- API
- thunks([scope])
- thunks.pruneErrorStack
- thunks.onerror(error)
- Class thunks.Scope
- thunk(thunkable)
- thunk.all(obj)
- thunk.all(thunkable1, ..., thunkableN)
- thunk.seq([thunkable1, ..., thunkableN])
- thunk.seq(thunkable1, ..., thunkableN)
- thunk.race([thunkable1, ..., thunkableN])
- thunk.race(thunkable1, ..., thunkableN)
- thunk.thunkify(fn)
- thunk.lift(fn)
- thunk.promise(thunkable)
- thunk.persist(thunkable)
- thunk.delay(delay)
- thunk.stop([message])
- thunk.cancel()
- TypeScript Typings
- What functions are thunkable
- License
Implementations
- Toa A powerful web framework rely on thunks.
- T-man Super test manager for JavaScript.
- thunk-redis The fastest thunk/promise-based redis client, support all redis features.
- thunk-disque A thunk/promise-based disque client.
- thunk-stream Wrap a readable/writable/duplex/transform stream to a thunk.
- thunk-queue A thunk queue for uncertainty tasks evaluation.
- thunk-loop Asynchronous tasks loop (while (true) { ... }).
- thunk-mocha Enable support for generators in Mocha with backward compatibility.
- thunk-ratelimiter The fastest abstract rate limiter.
- thunk-workers Thunk-based task scheduler that executes synchrounous and/or asynchronous tasks under concurrency control.
- file-cache Read file with caching, rely on thunks.
And a mountain of applications in server-side or client-side.
What is a thunk
-
thunkis a function that encapsulates synchronous or asynchronous code inside. -
thunkaccepts only onecallbackfunction as an arguments, which is a CPS function. -
thunkreturns anotherthunkfunction after being called, for chaining operations. -
thunkpasses the results into acallbackfunction after being excuted. -
If the return value of
callbackis athunkfunction, then it will be executed first and its result will be sent to anotherthunkfor excution, or it will be sent to another newthunkfunction as the value of the computation.
Demo
with thunk function
const thunk = require('thunks')()
const fs = require('fs')
thunk(function (done) {
fs.stat('package.json', done)
})(function (error, res) {
console.log(error, res)
})
with async function
thunk(async function () {
console.log(await Promise.resolve('await promise in an async function'))
try {
await new Promise((resolve, reject) => {
setTimeout(() => reject('catch promise error in async function'), 1000)
})
} catch (err) {
console.log(err)
}
})()
with generator function
const thunk = require('thunks')()
const fs = require('fs')
const size = thunk.thunkify(fs.stat)
// generator
thunk(function * () {
// yield thunk function
console.log(yield size('thunks.js'))
console.log(yield size('package.json'))
// yield async function
console.log(yield async () => 'yield an async function in generator function')
// yield generator function
console.log(yield function * () { return 'yield an async function in generator function' })
// parallel run
console.log(yield thunk.all([
size('thunks.js'),
size('package.json')
]))
})()
chain, sequential, parallel
const thunk = require('thunks')()
const fs = require('fs')
const 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)
})
// sequential
thunk.seq([
size('.gitignore'),
size('thunks.js'),
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)
})
Installation
Node.js:
npm install thunks
Bower:
bower install thunks
browser:
<script src="/pathTo/thunks.js"></script>
API
const thunks = require('thunks')
const { thunks, thunk, slice, Scope, isAsyncFn, isGeneratorFn, isThunkableFn } = from 'thunks'
thunks([scope])
Matrix of thunk, it generates a thunkFunction factory (named thunk) with it's scope.
"scope" refers to the running evironments thunk generated(directly or indirectly) for all child thunk functions.
- Here's how you create a basic
thunk, any exceptions would be passed the next child thunk function:
const thunk = thunks()
- Here's the way to create a
thunklistening to all exceptions in current scope withonerror, and it will make sure the exceptions are not being passed to the followed child thunk function, unlessonerrorfunction returnstrue.
const thunk = thunks(function (error) { console.error(error) })
Equals:
const scope = new thunks.Scope(function (error) { console.error(error) })
const thunk = thunks(scope)
- Create a
thunkwithonerror,onstopanddebuglisteners. Results of thisthunkwould be passed todebugfunction first before passing to the followed child thunk function.
const thunk = thunks({
onstop: function (sig) { console.log(sig) },
onerror: function (error) { console.error(error) },
debug: function () { console.log.apply(console, arguments) }
})
Equals:
const scope = new thunks.Scope({
onstop: function (sig) { console.log(sig) },
onerror: function (error) { console.error(error) },
debug: function () { console.log.apply(console, arguments) }
})
const thunk = thunks(scope)
The context of onerror, onstop and debug is a scope.
Even multiple thunk main functions with different scopes are composed,
each scope would be separate from each other,
which means, onerror, onstop and debug would not run in other scopes.
thunks.pruneErrorStack
Default to true, means it will prune error stack message.
thunks.onerror(error)
Default to null, it is a global error handler.
Class thunks.Scope
const scope = new thunks.Scope({
onstop: function (sig) { assert.strictEqual(this, scope) },
onerror: function (error) { assert.strictEqual(this, scope) },
debug: function () { assert.strictEqual(this, scope) }
})
const thunk = thunks(scope)
thunk(thunkable)
This is the thunkFunction factory, to create new thunkFunction functions.
The parameter thunkable value could be:
- a
thunkFunctionfunction, by calling this function a newthunkFunctionfunction will be returned
let thunk1 = thunk(1)
thunk(thunk1)(function (error, value) {
console.log(error, value) // null 1
})
- a thunkLike function
function (callback) {}, when called, passes its results to the nextthunkFunctionfunction
thunk(function (callback) {
callback(null, 1)
})(function (error, value) {
console.log(error, value) // null 1
})
- a Promise object, results of Promise would be passed to a new
thunkFunctionfunction
let promise = Promise.resolve(1)
thunk(promise)(function (error, value) {
console.log(error, value) // null 1
})
- objects which implements the method
toThunk
let obj = {
toThunk: function () {
return function (done) { done(null, 1) }
}
}
// `obj` has `toThunk` method that returns a thunk function
thunk(obj)(function (error, value) {
console.log(error, value) // null 1
})
- objects which implement the method
toPromise
const Rx = require('rxjs')
// Observable instance has `toPromise` method that returns a promise
thunk(Rx.Observable.fromPromise(Promise.resolve(123)))(function (error, value) {
console
