Skip to content
This repository was archived by the owner on Dec 1, 2023. It is now read-only.

Commit 76e012f

Browse files
committed
update to Promises/A+ polyfill
1 parent 7dbba59 commit 76e012f

File tree

1 file changed

+189
-33
lines changed

1 file changed

+189
-33
lines changed

src/lib/promise.js

Lines changed: 189 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,212 @@
11
/**
2-
* Promise polyfill. (https://gist.github.com/briancavalier/814313)
2+
* Promises/A+ polyfill v1.1.0 (https://github.com/bramstein/promis)
33
*/
44

5-
function Promise (executor) {
6-
executor(this.resolve.bind(this), this.reject.bind(this));
7-
this._thens = [];
5+
function Promise(executor) {
6+
7+
this.state = Promise.State.PENDING;
8+
this.value = undefined;
9+
this.deferred = [];
10+
11+
var promise = this;
12+
13+
try {
14+
executor(function (x) {
15+
promise.resolve(x);
16+
}, function (r) {
17+
promise.reject(r);
18+
});
19+
} catch (e) {
20+
promise.reject(e);
21+
}
822
}
923

10-
Promise.prototype = {
24+
Promise.State = {
25+
RESOLVED: 0,
26+
REJECTED: 1,
27+
PENDING: 2
28+
};
1129

12-
then: function (onResolve, onReject, onProgress) {
13-
this._thens.push({resolve: onResolve, reject: onReject, progress: onProgress});
14-
},
30+
Promise.reject = function (r) {
31+
return new Promise(function (resolve, reject) {
32+
reject(r);
33+
});
34+
};
35+
36+
Promise.resolve = function (x) {
37+
return new Promise(function (resolve, reject) {
38+
resolve(x);
39+
});
40+
};
1541

16-
'catch': function (onReject) {
17-
this._thens.push({reject: onReject});
18-
},
42+
Promise.all = function all(iterable) {
43+
return new Promise(function (resolve, reject) {
44+
var count = 0,
45+
result = [];
1946

20-
resolve: function (value) {
21-
this._complete('resolve', value);
22-
},
47+
if (iterable.length === 0) {
48+
resolve(result);
49+
}
2350

24-
reject: function (reason) {
25-
this._complete('reject', reason);
26-
},
51+
function resolver(i) {
52+
return function (x) {
53+
result[i] = x;
54+
count += 1;
2755

28-
progress: function (status) {
56+
if (count === iterable.length) {
57+
resolve(result);
58+
}
59+
};
60+
}
2961

30-
var i = 0, aThen;
62+
for (var i = 0; i < iterable.length; i += 1) {
63+
iterable[i].then(resolver(i), reject);
64+
}
65+
});
66+
};
3167

32-
while (aThen = this._thens[i++]) {
33-
aThen.progress && aThen.progress(status);
68+
Promise.race = function race(iterable) {
69+
return new Promise(function (resolve, reject) {
70+
for (var i = 0; i < iterable.length; i += 1) {
71+
iterable[i].then(resolve, reject);
3472
}
35-
},
73+
});
74+
};
3675

37-
_complete: function (which, arg) {
76+
var p = Promise.prototype;
3877

39-
this.then = which === 'resolve' ?
40-
function (resolve, reject) { resolve && resolve(arg); } :
41-
function (resolve, reject) { reject && reject(arg); };
78+
p.resolve = function resolve(x) {
79+
var promise = this;
4280

43-
this.resolve = this.reject = this.progress =
44-
function () { throw new Error('Promise already completed.'); };
81+
if (promise.state === Promise.State.PENDING) {
82+
if (x === promise) {
83+
throw new TypeError('Promise settled with itself.');
84+
}
85+
86+
var called = false;
87+
88+
try {
89+
var then = x && x['then'];
90+
91+
if (x !== null && typeof x === 'object' && typeof then === 'function') {
92+
then.call(x, function (x) {
93+
if (!called) {
94+
promise.resolve(x);
95+
}
96+
called = true;
97+
98+
}, function (r) {
99+
if (!called) {
100+
promise.reject(r);
101+
}
102+
called = true;
103+
});
104+
return;
105+
}
106+
} catch (e) {
107+
if (!called) {
108+
promise.reject(e);
109+
}
110+
return;
111+
}
112+
promise.state = Promise.State.RESOLVED;
113+
promise.value = x;
114+
promise.notify();
115+
}
116+
};
45117

46-
var aThen, i = 0;
118+
p.reject = function reject(reason) {
119+
var promise = this;
47120

48-
while (aThen = this._thens[i++]) {
49-
aThen[which] && aThen[which](arg);
121+
if (promise.state === Promise.State.PENDING) {
122+
if (reason === promise) {
123+
throw new TypeError('Promise settled with itself.');
50124
}
51125

52-
delete this._thens;
126+
promise.state = Promise.State.REJECTED;
127+
promise.value = reason;
128+
promise.notify();
53129
}
54130
};
55131

56-
module.exports = window.Promise ? window.Promise : Promise;
132+
p.notify = function notify() {
133+
var promise = this;
134+
135+
async(function () {
136+
if (promise.state !== Promise.State.PENDING) {
137+
while (promise.deferred.length) {
138+
var deferred = promise.deferred.shift(),
139+
onResolved = deferred[0],
140+
onRejected = deferred[1],
141+
resolve = deferred[2],
142+
reject = deferred[3];
143+
144+
try {
145+
if (promise.state === Promise.State.RESOLVED) {
146+
if (typeof onResolved === 'function') {
147+
resolve(onResolved.call(undefined, promise.value));
148+
} else {
149+
resolve(promise.value);
150+
}
151+
} else if (promise.state === Promise.State.REJECTED) {
152+
if (typeof onRejected === 'function') {
153+
resolve(onRejected.call(undefined, promise.value));
154+
} else {
155+
reject(promise.value);
156+
}
157+
}
158+
} catch (e) {
159+
reject(e);
160+
}
161+
}
162+
}
163+
});
164+
};
165+
166+
p.catch = function (onRejected) {
167+
return this.then(undefined, onRejected);
168+
};
169+
170+
p.then = function then(onResolved, onRejected) {
171+
var promise = this;
172+
173+
return new Promise(function (resolve, reject) {
174+
promise.deferred.push([onResolved, onRejected, resolve, reject]);
175+
promise.notify();
176+
});
177+
};
178+
179+
var queue = [];
180+
var async = function (callback) {
181+
queue.push(callback);
182+
183+
if (queue.length === 1) {
184+
async.async();
185+
}
186+
};
187+
188+
async.run = function () {
189+
while (queue.length) {
190+
queue[0]();
191+
queue.shift();
192+
}
193+
};
194+
195+
if (window.MutationObserver) {
196+
var el = document.createElement('div');
197+
var mo = new MutationObserver(async.run);
198+
199+
mo.observe(el, {
200+
attributes: true
201+
});
202+
203+
async.async = function () {
204+
el.setAttribute("x", 0);
205+
};
206+
} else {
207+
async.async = function () {
208+
setTimeout(async.run);
209+
};
210+
}
211+
212+
module.exports = window.Promise || Promise;

0 commit comments

Comments
 (0)