1 | // This file contains all the non-ES6-standard helpers based on promise.
|
2 |
|
3 | module.exports = {
|
4 |
|
5 | /**
|
6 | * A function that helps run functions under a concurrent limitation.
|
7 | * To run functions sequentially, use `yaku/lib/flow`.
|
8 | * @param {Int} limit The max task to run at a time. It's optional.
|
9 | * Default is `Infinity`.
|
10 | * @param {Iterable} list Any [iterable](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols) object. It should be a lazy iteralbe object,
|
11 | * don't pass in a normal Array with promises.
|
12 | * @return {Promise}
|
13 | * @example
|
14 | * ```js
|
15 | * var kit = require('nokit');
|
16 | * var all = require('yaku/lib/all');
|
17 | *
|
18 | * var urls = [
|
19 | * 'http://a.com',
|
20 | * 'http://b.com',
|
21 | * 'http://c.com',
|
22 | * 'http://d.com'
|
23 | * ];
|
24 | * var tasks = function * () {
|
25 | * var i = 0;
|
26 | * yield kit.request(url[i++]);
|
27 | * yield kit.request(url[i++]);
|
28 | * yield kit.request(url[i++]);
|
29 | * yield kit.request(url[i++]);
|
30 | * }();
|
31 | *
|
32 | * all(tasks).then(() => kit.log('all done!'));
|
33 | *
|
34 | * all(2, tasks).then(() => kit.log('max concurrent limit is 2'));
|
35 | *
|
36 | * all(3, { next: () => {
|
37 | * var url = urls.pop();
|
38 | * return {
|
39 | * done: !url,
|
40 | * value: url && kit.request(url)
|
41 | * };
|
42 | * } })
|
43 | * .then(() => kit.log('all done!'));
|
44 | * ```
|
45 | */
|
46 | all: require("./all"),
|
47 |
|
48 | /**
|
49 | * Similar with the `Promise.race`, but only rejects when every entry rejects.
|
50 | * @param {iterable} iterable An iterable object, such as an Array.
|
51 | * @return {Yaku}
|
52 | * @example
|
53 | * ```js
|
54 | * var any = require('yaku/lib/any');
|
55 | * any([
|
56 | * 123,
|
57 | * Promise.resolve(0),
|
58 | * Promise.reject(new Error("ERR"))
|
59 | * ])
|
60 | * .then((value) => {
|
61 | * console.log(value); // => 123
|
62 | * });
|
63 | * ```
|
64 | */
|
65 | any: require("./any"),
|
66 |
|
67 | /**
|
68 | * Generator based async/await wrapper.
|
69 | * @param {Generator} gen A generator function
|
70 | * @return {Yaku}
|
71 | * @example
|
72 | * ```js
|
73 | * var async = require('yaku/lib/async');
|
74 | * var sleep = require('yaku/lib/sleep');
|
75 | *
|
76 | * var fn = async(function * () {
|
77 | * return yield sleep(1000, 'ok');
|
78 | * });
|
79 | *
|
80 | * fn().then(function (v) {
|
81 | * console.log(v);
|
82 | * });
|
83 | * ```
|
84 | */
|
85 | async: require("./async"),
|
86 |
|
87 | /**
|
88 | * If a function returns promise, convert it to
|
89 | * node callback style function.
|
90 | * @param {Function} fn
|
91 | * @param {Any} self The `this` to bind to the fn.
|
92 | * @return {Function}
|
93 | */
|
94 | callbackify: require("./callbackify"),
|
95 |
|
96 | /**
|
97 | * **deprecate** Create a `jQuery.Deferred` like object.
|
98 | * It will cause some buggy problems, please don't use it.
|
99 | */
|
100 | Deferred: require("./Deferred"),
|
101 |
|
102 | /**
|
103 | * Creates a function that is the composition of the provided functions.
|
104 | * See `yaku/lib/async`, if you need concurrent support.
|
105 | * @param {Iterable} list Any [iterable](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols) object. It should be a lazy iteralbe object,
|
106 | * don't pass in a normal Array with promises.
|
107 | * @return {Function} `(val) -> Promise` A function that will return a promise.
|
108 | * @example
|
109 | * It helps to decouple sequential pipeline code logic.
|
110 | * ```js
|
111 | * var kit = require('nokit');
|
112 | * var flow = require('yaku/lib/flow');
|
113 | *
|
114 | * function createUrl (name) {
|
115 | * return "http://test.com/" + name;
|
116 | * }
|
117 | *
|
118 | * function curl (url) {
|
119 | * return kit.request(url).then((body) => {
|
120 | * kit.log('get');
|
121 | * return body;
|
122 | * });
|
123 | * }
|
124 | *
|
125 | * function save (str) {
|
126 | * kit.outputFile('a.txt', str).then(() => {
|
127 | * kit.log('saved');
|
128 | * });
|
129 | * }
|
130 | *
|
131 | * var download = flow(createUrl, curl, save);
|
132 | * // same as "download = flow([createUrl, curl, save])"
|
133 | *
|
134 | * download('home');
|
135 | * ```
|
136 | * @example
|
137 | * Walk through first link of each page.
|
138 | * ```js
|
139 | * var kit = require('nokit');
|
140 | * var flow = require('yaku/lib/flow');
|
141 | *
|
142 | * var list = [];
|
143 | * function iter (url) {
|
144 | * return {
|
145 | * done: !url,
|
146 | * value: url && kit.request(url).then((body) => {
|
147 | * list.push(body);
|
148 | * var m = body.match(/href="(.+?)"/);
|
149 | * if (m) return m[0];
|
150 | * });
|
151 | * };
|
152 | * }
|
153 | *
|
154 | * var walker = flow(iter);
|
155 | * walker('test.com');
|
156 | * ```
|
157 | */
|
158 | flow: require("./flow"),
|
159 |
|
160 | /**
|
161 | * Enable a helper to catch specific error type.
|
162 | * It will be directly attach to the prototype of the promise.
|
163 | * @param {class} type
|
164 | * @param {Function} onRejected
|
165 | * @return {Promise}
|
166 | * ```js
|
167 | * var Promise = require('yaku');
|
168 | * require('yaku/lib/guard');
|
169 | *
|
170 | * class AnError extends Error {
|
171 | * }
|
172 | *
|
173 | * Promise.reject(new AnError('hey'))
|
174 | * .guard(AnError, (err) => {
|
175 | * // only log AnError type
|
176 | * console.log(err);
|
177 | * })
|
178 | * .then(() => {
|
179 | * console.log('done');
|
180 | * })
|
181 | * .guard(Error, (err) => {
|
182 | * // log all error type
|
183 | * console.log(err)
|
184 | * });
|
185 | * ```
|
186 | */
|
187 | guard: require("./guard"),
|
188 |
|
189 | /**
|
190 | * if-else helper
|
191 | * @param {Promise} cond
|
192 | * @param {Function} trueFn
|
193 | * @param {Function} falseFn
|
194 | * @return {Promise}
|
195 | * @example
|
196 | * ```js
|
197 | * var Promise = require('yaku');
|
198 | * var yutils = require('yaku/lib/utils');
|
199 | *
|
200 | * yutils.if(Promise.resolve(false), () => {
|
201 | * // true
|
202 | * }, () => {
|
203 | * // false
|
204 | * })
|
205 | * ```
|
206 | */
|
207 | "if": require("./if"),
|
208 |
|
209 | /**
|
210 | * **deprecate** Check if an object is a promise-like object.
|
211 | * Don't use it to coercive a value to Promise, instead use `Promise.resolve`.
|
212 | * @param {Any} obj
|
213 | * @return {Boolean}
|
214 | */
|
215 | isPromise: require("./isPromise"),
|
216 |
|
217 | /**
|
218 | * Create a promise that never ends.
|
219 | * @return {Promise} A promise that will end the current pipeline.
|
220 | */
|
221 | never: require("./never"),
|
222 |
|
223 | /**
|
224 | * Convert a node callback style function to a function that returns
|
225 | * promise when the last callback is not supplied.
|
226 | * @param {Function} fn
|
227 | * @param {Any} self The `this` to bind to the fn.
|
228 | * @return {Function}
|
229 | * @example
|
230 | * ```js
|
231 | * var promisify = require('yaku/lib/promisify');
|
232 | * function foo (val, cb) {
|
233 | * setTimeout(() => {
|
234 | * cb(null, val + 1);
|
235 | * });
|
236 | * }
|
237 | *
|
238 | * var bar = promisify(foo);
|
239 | *
|
240 | * bar(0).then((val) => {
|
241 | * console.log val // output => 1
|
242 | * });
|
243 | *
|
244 | * // It also supports the callback style.
|
245 | * bar(0, (err, val) => {
|
246 | * console.log(val); // output => 1
|
247 | * });
|
248 | * ```
|
249 | */
|
250 | promisify: require("./promisify"),
|
251 |
|
252 | /**
|
253 | * Create a promise that will wait for a while before resolution.
|
254 | * @param {Integer} time The unit is millisecond.
|
255 | * @param {Any} val What the value this promise will resolve.
|
256 | * @return {Promise}
|
257 | * @example
|
258 | * ```js
|
259 | * var sleep = require('yaku/lib/sleep');
|
260 | * sleep(1000).then(() => console.log('after one second'));
|
261 | * ```
|
262 | */
|
263 | sleep: require("./sleep"),
|
264 |
|
265 | /**
|
266 | * Read the `Observable` section.
|
267 | * @type {Function}
|
268 | */
|
269 | Observable: require("./Observable"),
|
270 |
|
271 | /**
|
272 | * Retry a function until it resolves before a mount of times, or reject with all
|
273 | * the error states.
|
274 | * @version_added v0.7.10
|
275 | * @param {Number | Function} countdown How many times to retry before rejection.
|
276 | * @param {Number} span Optional. How long to wait before each retry in millisecond.
|
277 | * When it's a function `(errs) => Boolean | Promise.resolve(Boolean)`,
|
278 | * you can use it to create complex countdown logic,
|
279 | * it can even return a promise to create async countdown logic.
|
280 | * @param {Function} fn The function can return a promise or not.
|
281 | * @param {Any} this Optional. The context to call the function.
|
282 | * @return {Function} The wrapped function. The function will reject an array
|
283 | * of reasons that throwed by each try.
|
284 | * @example
|
285 | * Retry 3 times before rejection, wait 1 second before each retry.
|
286 | * ```js
|
287 | * var retry = require('yaku/lib/retry');
|
288 | * var { request } = require('nokit');
|
289 | *
|
290 | * retry(3, 1000, request)('http://test.com').then(
|
291 | * (body) => console.log(body),
|
292 | * (errs) => console.error(errs)
|
293 | * );
|
294 | * ```
|
295 | * @example
|
296 | * Here a more complex retry usage, it shows an random exponential backoff algorithm to
|
297 | * wait and retry again, which means the 10th attempt may take 10 minutes to happen.
|
298 | * ```js
|
299 | * var retry = require('yaku/lib/retry');
|
300 | * var sleep = require('yaku/lib/sleep');
|
301 | * var { request } = require('nokit');
|
302 | *
|
303 | * function countdown (retries) {
|
304 | * var attempt = 0;
|
305 | * return async () => {
|
306 | * var r = Math.random() * Math.pow(2, attempt) * 1000;
|
307 | * var t = Math.min(r, 1000 * 60 * 10);
|
308 | * await sleep(t);
|
309 | * return attempt++ < retries;
|
310 | * };
|
311 | * }
|
312 | *
|
313 | * retry(countdown(10), request)('http://test.com').then(
|
314 | * (body) => console.log(body),
|
315 | * (errs) => console.error(errs)
|
316 | * );
|
317 | * ```
|
318 | */
|
319 | retry: require("./retry"),
|
320 |
|
321 | /**
|
322 | * Throw an error to break the program.
|
323 | * @param {Any} err
|
324 | * @example
|
325 | * ```js
|
326 | * var ythrow = require('yaku/lib/throw');
|
327 | * Promise.resolve().then(() => {
|
328 | * // This error won't be caught by promise.
|
329 | * ythrow('break the program!');
|
330 | * });
|
331 | * ```
|
332 | */
|
333 | "throw": require("./throw"),
|
334 |
|
335 | /**
|
336 | * Create a promise that will reject after a while if the passed in promise
|
337 | * doesn't settle first.
|
338 | * @param {Promise} promise The passed promise to wait.
|
339 | * @param {Integer} time The unit is millisecond.
|
340 | * @param {Any} reason After time out, it will be the reject reason.
|
341 | * @return {Promise}
|
342 | * @example
|
343 | * ```js
|
344 | * var sleep = require('yaku/lib/sleep');
|
345 | * var timeout = require('yaku/lib/timeout');
|
346 | * timeout(sleep(500), 100)["catch"]((err) => {
|
347 | * console.error(err);
|
348 | * });
|
349 | * ```
|
350 | */
|
351 | timeout: require("./timeout")
|
352 | };
|