# 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
```

[![build status](http://img.shields.io/travis/mafintosh/thunky.svg?style=flat)](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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bryan-guner.gitbook.io/my-docs/redux/repos/examples/real-world/node_modules/thunky.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
