forked from kriskowal/q
-
Notifications
You must be signed in to change notification settings - Fork 0
/
README
238 lines (159 loc) · 6.71 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
Provides a defer/when style promise API for JavaScript
- usable as a CommonJS module, in Node,
- usable as a <script> in all web browsers,
- inspired by Tyler Close's Waterken ref_send promises, and
- compliant with http://wiki.commonjs.org/wiki/Promises/B
For Node:
$ curl http://npmjs.org/install.sh | sh
$ npm install q
$ node examples/test.js
The Q Ecosystem:
q-fs https://github.com/kriskowal/q-fs
basic file system promises
q-http https://github.com/kriskowal/q-http
http client and server promises
q-util https://github.com/kriskowal/q-util
promise control flow and data structures
teleport https://github.com/gozala/teleport
browser-side module promises
...
All available through NPM.
THE HALLOWED API
when(value, callback_opt, errback_opt)
Arranges for a callback to be called:
- with the value as its sole argument
- in a future turn of the event loop
- if and when the value is or becomes a fully resolved
Arranges for errback to be called:
- with a value respresenting the reason why the object will
never be resolved, typically a string.
- in a future turn of the event loop
- if the value is a promise and
- if and when the promise is rejected
Returns a promise:
- that will resolve to the value returned by either the callback
or errback, if either of those functions are called, or
- that will be rejected if the value is rejected and no errback
is provided, thus forwarding rejections by default.
The value may be truly _any_ value.
The callback and errback may be falsy, in which case they will not
be called.
Guarantees:
- The callback will not be called before when returns.
- The errback will not be called before when returns.
- The callback will not be called more than once.
- The errback will not be called more than once.
- If the callback is called, the errback will never be called.
- If the errback is called, the callback will never be called.
- If a promise is never resolved, neither the callback or the
errback will ever be called.
THIS IS COOL
- You can set up an entire chain of causes and effects in the
duration of a single event and be guaranteed that any
invariants in your lexical scope will not...vary.
- You can both receive a promise from a sketchy API and return a
promise to some other sketchy API and, as long as you trust
this module, all of these guarantees are still provided.
- You can use when to compose promises in a variety of ways:
INTERSECTION
function and(a, b) {
return when(a, function (a) {
return when(b, function (b) {
// ...
});
})
}
defer()
Returns a "Deferred" object with a:
- promise property
- resolve(value) function
- reject(reason) function
The promise is suitable for passing as a value to
the "when" function.
Calling resolve with a promise notifies all observers
that they must now wait for that promise to resolve.
Calling resolve with a rejected promise notifies all
observers that the promise will never be fully resolved
with the rejection reason. This forwards through the
the chain of "when" calls and their returned "promises"
until it reaches a "when" call that has an "errback".
Calling resolve with a fully resolved value notifies
all observers that they may proceed with that value
in a future turn. This forwards through the "callback"
chain of any pending "when" calls.
Calling reject with a reason is equivalent to
resolving with a rejection.
In all cases where the resolution of a promise is set,
(promise, rejection, value) the resolution is permanent
and cannot be reset. All future observers of the
resolution of the promise will be notified of the
resolved value, so it is safe to call "when" on
a promise regardless of whether it has been or will
be resolved.
THIS IS COOL
The Deferred separates the promise part from the resolver
part. So:
- You can give the promise to any number of consumers
and all of them will observe the resolution independently.
Because the capability of observing a promise is separated
from the capability of resolving the promise, none of the
recipients of the promise have the ability to "trick"
other recipients with misinformation.
- You can give the resolver to any number of producers
and whoever resolves the promise first wins. Furthermore,
none of the producers can observe that they lost unless
you give them the promise part too.
UNION
function or(a, b) {
var union = defer();
when(a, union.resolve);
when(b, union.resolve);
return union.promise;
}
ref(value)
If value is a promise, returns the value.
If value is not a promise, returns a promise that has
already been resolved with the given value.
reject(reason)
Returns a promise that has already been rejected
with the given reason.
This is useful for conditionally forwarding a rejection through an
errback.
when(API.getPromise(), function (value) {
return doSomething(value);
}, function (reason) {
if (API.stillPossible())
return API.tryAgain();
else
return reject(reason);
})
Unconditionally forwarding a rejection is equivalent to omitting
an errback on a when call.
isPromise(value)
Returns whether the given value is a promise.
isResolved(value)
Returns whether the given value is fully resolved.
The given value may be any value, including
but not limited to promises returned by defer() and
ref(). Rejected promises are not considered
resolved.
isRejected(value)
Returns whether the given value is a rejected
promise.
promise.valueOf()
Promises override their valueOf method such that if the
promise is fully resolved, it will return the fully
resolved value.
defined(value)
Accepts a value or a promise for a value.
Returns a promise that will only resolve to a defined value.
If the given promise is resolved to "undefined", rejects
the returned promise.
error(reason)
Accepts a reason and throws an error. This is a convenience for
when calls where you want to trap the error clause and throw it
instead of attempting a recovery or forwarding.
enqueue(callback Function)
Calls "callback" in a future turn.
Copyright 2009, 2010 Kristopher Michael Kowal
MIT License (enclosed)