forked from cujojs/when
-
Notifications
You must be signed in to change notification settings - Fork 0
/
generator.js
105 lines (91 loc) · 2.53 KB
/
generator.js
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
/** @license MIT License (c) copyright 2010-2014 original author or authors */
/** @author Brian Cavalier */
/** @author John Hann */
(function(define) { 'use strict';
define(function(require) {
var when = require('./when');
var slice = Array.prototype.slice;
var Promise = when.Promise;
var reject = Promise.reject;
/**
* Lift a generator to create a function that can suspend and
* resume using the `yield` keyword to await promises.
* @param {function} generator
* @return {function}
*/
function lift(generator) {
return function() {
return run(generator, this, arguments);
};
}
/**
* Immediately call a generator as a promise-aware coroutine
* that can suspend and resume using the `yield` keyword to
* await promises. Additional arguments after the first will
* be passed through to the generator.
* @param {function} generator
* @returns {Promise} promise for the ultimate value returned
* from the generator.
*/
function call(generator /*x, y, z...*/) {
/*jshint validthis:true*/
return run(generator, this, slice.call(arguments, 1));
}
/**
* Immediately apply a generator, with the supplied args array,
* as a promise-aware coroutine that can suspend and resume
* using the `yield` keyword to await promises.
* @param {function} generator
* @param {Array} args arguments with which to initialize the generator
* @returns {Promise} promise for the ultimate value returned
* from the generator.
*/
function apply(generator, args) {
/*jshint validthis:true*/
return run(generator, this, args || []);
}
/**
* Helper to initiate the provided generator as a coroutine
* @returns {*}
*/
function run(generator, thisArg, args) {
return runNext(void 0, generator.apply(thisArg, args));
}
function runNext(x, iterator) {
try {
return handle(iterator.next(x), iterator);
} catch(e) {
return reject(e);
}
}
function next(x) {
/*jshint validthis:true*/
return runNext(x, this);
}
function error(e) {
/*jshint validthis:true*/
try {
return handle(this.throw(e), this);
} catch(e) {
return reject(e);
}
}
function handle(result, iterator) {
if(result.done) {
return result.value;
}
var h = Promise._handler(result.value);
if(h.state() > 0) {
return runNext(h.value, iterator);
}
var p = Promise._defer();
h.chain(p._handler, iterator, next, error);
return p;
}
return {
lift: lift,
call: call,
apply: apply
};
});
}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));