Pathologic was missing because of a .git folder inside.
[yaffs-website] / node_modules / kew / README.md
1 kew: a lightweight (and super fast) promise/deferred framework for node.js
2 ==================================
3
4 [![Build Status](https://travis-ci.org/Medium/kew.svg)](https://travis-ci.org/Medium/kew)
5
6 **kew** is a lightweight promise framework with an aim of providing a base set of functionality similar to that provided by the [Q library](https://github.com/kriskowal/q "Q").
7
8 A few answers (for a few questions)
9 -------
10
11 *Why'd we write it?*
12
13 During our initial usage of **Q** we found that it was consuming 80% of the cpu under load (primarily in chained database callbacks). We spent some time looking at patching **Q** and ultimately found that creating our own lightweight library for server-usage would suit our needs better than figuring out how to make a large cross-platform library more performant on one very specific platform.
14
15 *So this does everything Q does?*
16
17 Nope! **Q** is still an awesome library and does *way* more than **kew**. We support a tiny subset of the **Q** functionality (the subset that we happen to use in our actual use cases).
18
19 What are Promises?
20 -------
21
22 At its core, a *Promise* is a promise to return a value at some point in the future. A *Promise* represents a value that will be (or may return an error if something goes wrong). *Promises* heavily reduce the complexity of asynchronous coding in node.js-like environments. Example:
23
24 ```javascript
25 // assuming the getUrlContent() function exists and retrieves the content of a url
26 var htmlPromise = getUrlContent(myUrl)
27
28 // we can then filter that through an http parser (our imaginary parseHtml() function) asynchronously (or maybe synchronously, who knows)
29 var tagsPromise = htmlPromise.then(parseHtml)
30
31 // and then filter it through another function (getLinks()) which retrieves only the link tags
32 var linksPromise = tagsPromise.then(getLinks)
33
34 // and then parses the actual urls from the links (using parseUrlsFromLinks())
35 var urlsPromise = linksPromise.then(parseUrlsFromLinks)
36
37 // finally, we have a promise that should only provide us with the urls and will run once all the previous steps have ran
38 urlsPromise.then(function (urls) {
39   // do something with the urls
40 })
41 ```
42
43 How do I use **kew**?
44 -------
45
46 As a precursor to all the examples, the following code must be at the top of your page:
47
48 ```javascript
49 var Q = require('kew')
50 ```
51
52 ### Convert a literal into a promise
53
54 The easiest way to start a promise chain is by creating a new promise with a specified literal using Q.resolve() or Q.reject()
55
56 ```javascript
57 // create a promise which passes a value to the next then() call
58 var successPromise = Q.resolve(val)
59
60 // create a promise which throws an error to be caught by the next fail() call
61 var failPromise = Q.reject(err)
62 ```
63
64 In addition, you can create deferreds which can be used if you need to create a promise but resolve it later:
65
66 ```javascript
67 // create the deferreds
68 var successDefer = Q.defer()
69 var failDefer = Q.defer()
70
71 // resolve or reject the defers in 1 second
72 setTimeout(function () {
73   successDefer.resolve("ok")
74   failDefer.reject(new Error("this failed"))
75 }, 1000)
76
77 // extract promises from the deferreds
78 var successPromise = successDefer.promise
79 var failPromise = failDefer.promise
80 ```
81
82 If you have a node-style callback (taking an **Error** as the first parameter and a response as the second), you can call the magic `makeNodeResolver()` function on a defer to allow the defer to handle the callbacks:
83
84 ```javascript
85 // create the deferred
86 var defer = Q.defer()
87
88 // some node-style function
89 getObjectFromDatabase(myObjectId, defer.makeNodeResolver())
90
91 // grab the output
92 defer.promise
93   .then(function (obj) {
94     // successfully retrieved the object
95   })
96   .fail(function (e) {
97     // failed retrieving the object
98   })
99 ```
100
101 ### Handling successful results with `.then()`
102
103 When a promise is resolved, you may call the `.then()` method to retrieve the value of the promise:
104
105 ```javascript
106 promise.then(function (result) {
107   // do something with the result here
108 })
109 ```
110
111 `.then()` will in turn return a promise which will return the results of whatever it returns (asynchronously or not), allowing it to be chained indefinitely:
112
113 ```javascript
114 Q.resolve('a')
115   .then(function (result) {
116     return result + 'b'
117   })
118   .then(function (result) {
119     return result + 'c'
120   })
121   .then(function (result) {
122     // result should be 'abc'
123   })
124 ```
125
126 In addition, `.then()` calls may return promises themselves, allowing for complex nesting of asynchronous calls in a flat manner:
127
128 ```javascript
129 var htmlPromise = getUrlContent(myUrl)
130
131 var tagsPromise = htmlPromise.then(function (html) {
132   if (!validHtml(html)) throw new Error("Invalid HTML")
133
134   // pretend that parseHtml() returns a promise and is asynchronous
135   return parseHtml(html)
136 })
137 ```
138
139 ### Handling errors with `.fail()`
140
141 If a promise is rejected for some reason, you may handle the failure case with the `.fail()` function:
142
143 ```javascript
144 getObjectPromise
145   .fail(function (e) {
146     console.error("Failed to retrieve object", e)
147   })
148 ```
149
150 Like `.then()`, `.fail()` also returns a promise. If the `.fail()` call does not throw an error, it will pass the return value of the `.fail()` handler to any `.then()` calls chained to it:
151
152 ```javascript
153 getObjectPromise
154   .fail(function (e) {
155     return retryGetObject(objId)
156   })
157   .then(function (obj) {
158     // yay, we received an object
159   })
160   .fail(function (e) {
161     // the retry failed :(
162     console.error("Retrieving the object '" + objId + "' failed")
163   })
164 })
165 ```
166
167 If you've reached the end of your promise chain, you may call `.end()` which signifies that the promise chain is ended and any errors should be thrown in whatever scope the code is currently in:
168
169 ```javascript
170 getObjectPromise
171   // this will throw an error to the uncaught exception handler if the getObjectPromise call is asynchronous
172   .end()
173 ```
174
175 ### `.fin()` when things are finished
176
177 You may attach a handler to a promise which will be ran regardless of whether the promise was resolved or rejected (but will only run upon completion). This is useful in the cases where you may have set up resources to run a request and wish to tear them down afterwards. `.fin()` will return the promise it is called upon:
178
179 ```javascript
180 var connection = db.connect()
181
182 var itemPromise = db.getItem(itemId)
183   .fin(function () {
184     db.close()
185   })
186 ```
187
188 Other utility methods
189 -------
190
191 ### `.all()` for many things
192
193 If you're waiting for multiple promises to return, you may pass them (mixed in with literals if you desire) into `.all()` which will create a promise that resolves successfully with an array of the results of the promises:
194
195 ```javascript
196 var promises = []
197 promises.push(getUrlContent(url1))
198 promises.push(getUrlContent(url2))
199 promises.push(getUrlContent(url3))
200
201 Q.all(promises)
202   .then(function (content) {
203     // content[0] === content for url 1
204     // content[1] === content for url 2
205     // content[2] === content for url 3
206   })
207 ```
208
209 If any of the promises fail, Q.all will fail as well (so make sure to guard your promises with a `.fail()` call beforehand if you don't care whether they succeed or not):
210
211 ```javascript
212 var promises = []
213 promises.push(getUrlContent(url1))
214 promises.push(getUrlContent(url2))
215 promises.push(getUrlContent(url3))
216
217 Q.all(promises)
218   .fail(function (e) {
219     console.log("Failed retrieving a url", e)
220   })
221 ```
222
223 ### `.delay()` for future promises
224
225 If you need a little bit of delay (such as retrying a method call to a service that is "eventually consistent") before doing something else, ``Q.delay()`` is your friend:
226
227 ```javascript
228 getUrlContent(url1)
229 .fail(function () {
230   // Retry again after 200 milisseconds
231   return Q.delay(200).then(function () {
232     return getUrlContent(url1)
233   })
234 })
235 ```
236
237 If two arguments are passed, the first will be used as the return value, and the
238 second will be the delay in milliseconds.
239
240 ```javascript
241 Q.delay(obj, 20).then(function (result) {
242   console.log(result) // logs `obj` after 20ms
243 })
244 ```
245
246 ### `.fcall()` for delaying a function invocation until the next tick:
247 ```javascript
248 // Assume someFn() is a synchronous 2 argument function you want to delay.
249 Q.fcall(someFn, arg1, arg2)
250   .then(function (result) {
251     console.log('someFn(' + arg1 + ', ' + arg2 + ') = ' + result)
252   })
253 ```
254
255 You can also use ``Q.fcall()`` with functions that return promises.
256
257 ### `.ncall()` and `.nfcall()` for Node.js callbacks
258
259 ``Q.nfcall()`` can be used to convert node-style callbacks into promises:
260
261 ```javascript
262 Q.nfcall(fs.writeFile, '/tmp/myFile', 'content')
263   .then(function () {
264     console.log('File written successfully')
265   })
266   .fail(function (err) {
267     console.log('Failed to write file', err)
268   })
269 ```
270
271 If your Node-style callback needs a `this` context, you can use `Q.ncall`:
272
273 ```js
274 Q.ncall(redis.del, redis, 'my-key')
275   .then(function () { return true })
276   .fail(function () { return false })
277 ```
278
279
280 ### `.spread()` for arrays of promises
281
282 ``()`` can be used to convert node-style callbacks into promises:
283
284 ```javascript
285 Q.nfcall(function () {
286   return ['a', Q.resolve('b')]
287 })
288 .spread(function (a, b) { 
289   // ...
290 })
291 ```
292
293
294 Contributing
295 ------------
296
297 Questions, comments, bug reports, and pull requests are all welcome.
298 Submit them at [the project on GitHub](https://github.com/Obvious/kew/).
299
300 Bug reports that include steps-to-reproduce (including code) are the
301 best. Even better, make them in the form of pull requests that update
302 the test suite. Thanks!
303
304
305 Author
306 ------
307
308 [Jeremy Stanley](https://github.com/azulus)
309 supported by
310 [The Obvious Corporation](http://obvious.com/).
311
312
313 License
314 -------
315
316 Copyright 2013 [The Obvious Corporation](http://obvious.com/).
317
318 Licensed under the Apache License, Version 2.0.
319 See the top-level file `LICENSE.TXT` and
320 (http://www.apache.org/licenses/LICENSE-2.0).