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
|
/**
* Module dependencies.
*/
var util = require('./utils');
var EventEmitter = util.EventEmitter;
/**
* Promise constructor.
*
* @param {Function} a callback+errback that takes err, ... as signature
* @api public
*/
function Promise (back) {
this.emitted = {};
if ('function' == typeof back)
this.addBack(back);
};
/**
* Inherits from EventEmitter.
*/
Promise.prototype.__proto__ = EventEmitter.prototype;
/**
* Adds an event or fires the callback right away.
*
* @return promise
* @api public
*/
Promise.prototype.on = function (event, callback) {
if (this.emitted[event])
callback.apply(this, this.emitted[event]);
else
EventEmitter.prototype.on.call(this, event, callback);
return this;
};
/**
* Keeps track of emitted events to run them on `on`
*
* @api private
*/
Promise.prototype.emit = function (event) {
// ensures a promise can't be complete() or error() twice
if (event == 'err' || event == 'complete'){
if (this.emitted.err || this.emitted.complete) {
return this;
}
this.emitted[event] = util.args(arguments, 1);
}
return EventEmitter.prototype.emit.apply(this, arguments);
};
/**
* Shortcut for emitting complete event
*
* @api public
*/
Promise.prototype.complete = function () {
var args = util.args(arguments);
return this.emit.apply(this, ['complete'].concat(args));
};
/**
* Shortcut for emitting err event
*
* @api public
*/
Promise.prototype.error = function () {
var args = util.args(arguments);
return this.emit.apply(this, ['err'].concat(args));
};
/**
* Shortcut for `.on('complete', fn)`
*
* @return promise
* @api public
*/
Promise.prototype.addCallback = function (fn) {
return this.on('complete', fn);
};
/**
* Shortcut for `.on('err', fn)`
*
* @return promise
* @api public
*/
Promise.prototype.addErrback = function (fn) {
return this.on('err', fn);
};
/**
* Adds a single function that's both callback and errback
*
* @return promise
* @api private
*/
Promise.prototype.addBack = function (fn) {
this.on('err', function(err){
fn.call(this, err);
});
this.on('complete', function(){
var args = util.args(arguments);
fn.apply(this, [null].concat(args));
});
return this;
};
/**
* Sugar for handling cases where you may be
* resolving to either an error condition or a
* success condition.
*
* @param {Error} optional error or null
* @param {Object} value to complete the promise with
* @api public
*/
Promise.prototype.resolve = function (err, val) {
if (err) return this.error(err);
return this.complete(val);
};
/**
* Module exports.
*/
module.exports = Promise;
|