-
Notifications
You must be signed in to change notification settings - Fork 0
/
promises.js
104 lines (97 loc) · 2.23 KB
/
promises.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
module.exports = {Promises: Promises, PromisesLite: PromisesLite};
function Promises (err, done) {
this.err = err;
this.done = done;
this.nexts = [];
}
Promises.prototype = {
constructor: Promises,
state: '', // reject or resolve
value: null,
then: function (err, done) {
var next = new Promises(err, done);
this.nexts.push(next);
return next;
},
resolve: function (o) {
process.nextTick(function () { this._do(this.done, 'resolve', o); }.bind(this));
},
reject: function (o) {
process.nextTick(function () { this._do(this.err, 'reject', o); }.bind(this));
},
isResolved: function () {
return this.state !== '' && this.state === 'resolve';
},
isRejected: function () {
return this.state !== '' && this.state === 'reject';
},
_do: function (fn, type, o) {
if (this.state) return this.value;
if (o instanceof Promises) {
if (o.state) {
this._do(fn, o.state, o.value);
} else {
o.nexts.push(this);
}
} else if (o && typeof o.then === 'function') {
var p = new Promises();
p.nexts.push(this);
o.then(p.resolve, p.rejected);
} else {
type = 'resolve';
if (typeof fn === 'function') {
try {
fn = fn(o);
} catch (e) {
type = 'reject';
fn = e;
}
}
this.state = type;
this.value = fn;
this._notify(type, fn);
}
},
_notify: function (type, value) {
var next, nexts = this.nexts;
while (next = nexts.shift()) {
next[type](value);
}
}
};
function PromisesLite (err, done) {
this.err = err;
this.done = done;
}
PromisesLite.prototype = {
constructor: PromisesLite,
then: function (err, done) {
this.next = new PromisesLite(err, done);
return this.next;
},
resolve: function () {
process.nextTick(function () {
this._do.call(this, this.done, 'resolve', arguments).bind(this);
});
},
reject: function () {
process.nextTick(function () {
this._do.call(this, this.err, 'reject', arguments).bind(this);
});
},
_do: function (fn, type, args) {
if (args[0] instanceof Promises) {
args[0].next = this;
} else {
if (typeof fn === 'function') {
try {
fn = fn.apply(null, args);
} catch (e) {
this.next && this.next['reject'](e);
return;
}
}
this.next && this.next['resolve'](fn);
}
}
};