You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					98 lines
				
				2.4 KiB
			
		
		
			
		
	
	
					98 lines
				
				2.4 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								# thunky
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Delay the evaluation of a paramless async function and cache the result (see [thunk](http://en.wikipedia.org/wiki/Thunk_%28functional_programming%29)).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								npm install thunky
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[](http://travis-ci.org/mafintosh/thunky)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Example
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Let's make a simple function that returns a random number 1 second after it is called for the first time
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								``` js
							 | 
						||
| 
								 | 
							
								var thunky = require('thunky')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var test = thunky(function (callback) { // the inner function should only accept a callback
							 | 
						||
| 
								 | 
							
								  console.log('waiting 1s and returning random number')
							 | 
						||
| 
								 | 
							
								  setTimeout(function () {
							 | 
						||
| 
								 | 
							
								    callback(Math.random())
							 | 
						||
| 
								 | 
							
								  }, 1000)
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								test(function (num) {  // inner function is called the first time we call test
							 | 
						||
| 
								 | 
							
								  console.log(num) // prints random number
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								test(function (num) {  // subsequent calls waits for the first call to finish and return the same value
							 | 
						||
| 
								 | 
							
								  console.log(num) // prints the same random number as above
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Lazy evaluation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Thunky makes it easy to implement a lazy evaluation pattern.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								``` js
							 | 
						||
| 
								 | 
							
								var getDb = thunky(function (callback) {
							 | 
						||
| 
								 | 
							
								  db.open(myConnectionString, callback)
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var queryDb = function (query, callback) {
							 | 
						||
| 
								 | 
							
								  getDb(function (err, db) {
							 | 
						||
| 
								 | 
							
								    if (err) return callback(err)
							 | 
						||
| 
								 | 
							
								    db.query(query, callback)
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								queryDb('some query', function (err, result) { ... } )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								queryDb('some other query', function (err, result) { ... } )
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The first time `getDb` is called it will try do open a connection to the database.
							 | 
						||
| 
								 | 
							
								Any subsequent calls will just wait for the first call to complete and then call your callback.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								A nice property of this pattern is that it *easily* allows us to pass any error caused by `getDb` to the `queryDb` callback.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Error → No caching
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								If the thunk callback is called with an `Error` object as the first argument it will not cache the result
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								``` js
							 | 
						||
| 
								 | 
							
								var fails = thunky(function (callback) {
							 | 
						||
| 
								 | 
							
								  console.log('returning an error')
							 | 
						||
| 
								 | 
							
								  callback(new Error('bad stuff'))
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fails(function (err) { // inner function is called
							 | 
						||
| 
								 | 
							
								  console.log(err)
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fails(function (err) { // inner function is called again as it returned an error before
							 | 
						||
| 
								 | 
							
								  console.log(err)
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Promise version
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								A promise version is available as well
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								``` js
							 | 
						||
| 
								 | 
							
								var thunkyp = require('thunky/promise')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var ready = thunkyp(async function () {
							 | 
						||
| 
								 | 
							
								  // ... do async stuff
							 | 
						||
| 
								 | 
							
								  return 42
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// same semantics as the callback version
							 | 
						||
| 
								 | 
							
								await ready()
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## License
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								MIT
							 |