UNPKG

2.59 kBJavaScriptView Raw
1/** @license MIT License (c) copyright 2010-2014 original author or authors */
2/** @author Brian Cavalier */
3/** @author John Hann */
4
5(function(define) { 'use strict';
6define(function(require) {
7
8 var when = require('./when');
9 var slice = Array.prototype.slice;
10
11 /**
12 * Lift a generator to create a function that can suspend and
13 * resume using the `yield` keyword to await promises.
14 * @param {function} generator
15 * @return {function}
16 */
17 function lift(generator) {
18 return function() {
19 return run(generator, this, arguments);
20 };
21 }
22
23 /**
24 * Immediately call a generator as a promise-aware coroutine
25 * that can suspend and resume using the `yield` keyword to
26 * await promises. Additional arguments after the first will
27 * be passed through to the generator.
28 * @param {function} generator
29 * @returns {Promise} promise for the ultimate value returned
30 * from the generator.
31 */
32 function call(generator /*x, y, z...*/) {
33 /*jshint validthis:true*/
34 return run(generator, this, slice.call(arguments, 1));
35 }
36
37 /**
38 * Immediately apply a generator, with the supplied args array,
39 * as a promise-aware coroutine that can suspend and resume
40 * using the `yield` keyword to await promises.
41 * @param {function} generator
42 * @param {Array} args arguments with which to initialize the generator
43 * @returns {Promise} promise for the ultimate value returned
44 * from the generator.
45 */
46 function apply(generator, args) {
47 /*jshint validthis:true*/
48 return run(generator, this, args || []);
49 }
50
51 /**
52 * Helper to initiate the provided generator as a coroutine
53 * @returns {*}
54 */
55 function run(generator, thisArg, args) {
56 var stepper = new Stepper(next, error, generator.apply(thisArg, args));
57
58 return stepper.step('next', void 0);
59
60 function next(x) { return stepper.step('next', x); }
61 function error(e) { return stepper.step('throw', e); }
62 }
63
64 /**
65 * Manages the process of stepping the provided iterator
66 * @constructor
67 */
68 function Stepper(next, error, iterator) {
69 this.next = next;
70 this.error = error;
71 this.iterator = iterator;
72 }
73
74 Stepper.prototype.step = function(action, x) {
75 try {
76 return this._continue(action, x);
77 } catch (e) {
78 return when.reject(e);
79 }
80 };
81
82 Stepper.prototype._continue = function(action, x) {
83 var result = this.iterator[action](x);
84 return result.done ? result.value : when(result.value, this.next, this.error);
85 };
86
87 return {
88 lift: lift,
89 call: call,
90 apply: apply
91 };
92
93});
94}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));