Skip to content

Commit 5ff4fca

Browse files
Merge pull request then#88 from then/avoid-prototype
Avoid attaching unnecessary methods to the prototype
2 parents dc5a7f6 + c206f87 commit 5ff4fca

File tree

1 file changed

+55
-58
lines changed

1 file changed

+55
-58
lines changed

src/core.js

Lines changed: 55 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ function tryCallTwo(fn, a, b) {
5050
}
5151

5252
module.exports = Promise;
53+
5354
function Promise(fn) {
5455
if (typeof this !== 'object') {
5556
throw new TypeError('Promises must be constructed via new');
@@ -63,55 +64,54 @@ function Promise(fn) {
6364
if (fn === noop) return;
6465
doResolve(fn, this);
6566
}
66-
Promise.prototype._safeThen = function (onFulfilled, onRejected) {
67-
var self = this;
68-
return new this.constructor(function (resolve, reject) {
69-
var res = new Promise(noop);
70-
res.then(resolve, reject);
71-
self._handle(new Handler(onFulfilled, onRejected, res));
72-
});
73-
};
67+
7468
Promise.prototype.then = function(onFulfilled, onRejected) {
7569
if (this.constructor !== Promise) {
76-
return this._safeThen(onFulfilled, onRejected);
70+
return safeThen(this, onFulfilled, onRejected);
7771
}
7872
var res = new Promise(noop);
79-
this._handle(new Handler(onFulfilled, onRejected, res));
73+
handle(this, new Handler(onFulfilled, onRejected, res));
8074
return res;
8175
};
82-
Promise.prototype._handle = function(deferred) {
83-
if (this._state === 3) {
84-
this._value._handle(deferred);
85-
return;
76+
77+
function safeThen(self, onFulfilled, onRejected) {
78+
return new self.constructor(function (resolve, reject) {
79+
var res = new Promise(noop);
80+
res.then(resolve, reject);
81+
handle(self, new Handler(onFulfilled, onRejected, res));
82+
});
83+
};
84+
function handle(self, deferred) {
85+
while (self._state === 3) {
86+
self = self._value;
8687
}
87-
if (this._state === 0) {
88-
this._deferreds.push(deferred);
88+
if (self._state === 0) {
89+
self._deferreds.push(deferred);
8990
return;
9091
}
91-
var state = this._state;
92-
var value = this._value;
9392
asap(function() {
94-
var cb = state === 1 ? deferred.onFulfilled : deferred.onRejected;
93+
var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
9594
if (cb === null) {
96-
if (state === 1) {
97-
deferred.promise._resolve(value);
95+
if (self._state === 1) {
96+
resolve(deferred.promise, self._value);
9897
} else {
99-
deferred.promise._reject(value);
98+
reject(deferred.promise, self._value);
10099
}
101100
return;
102101
}
103-
var ret = tryCallOne(cb, value);
102+
var ret = tryCallOne(cb, self._value);
104103
if (ret === IS_ERROR) {
105-
deferred.promise._reject(LAST_ERROR);
104+
reject(deferred.promise, LAST_ERROR);
106105
} else {
107-
deferred.promise._resolve(ret);
106+
resolve(deferred.promise, ret);
108107
}
109108
});
110-
};
111-
Promise.prototype._resolve = function(newValue) {
109+
}
110+
function resolve(self, newValue) {
112111
// Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
113-
if (newValue === this) {
114-
return this._reject(
112+
if (newValue === self) {
113+
return reject(
114+
self,
115115
new TypeError('A promise cannot be resolved with itself.')
116116
);
117117
}
@@ -121,40 +121,37 @@ Promise.prototype._resolve = function(newValue) {
121121
) {
122122
var then = getThen(newValue);
123123
if (then === IS_ERROR) {
124-
return this._reject(LAST_ERROR);
124+
return reject(self, LAST_ERROR);
125125
}
126126
if (
127-
then === this.then &&
128-
newValue instanceof Promise &&
129-
newValue._handle === this._handle
127+
then === self.then &&
128+
newValue instanceof Promise
130129
) {
131-
this._state = 3;
132-
this._value = newValue;
133-
for (var i = 0; i < this._deferreds.length; i++) {
134-
newValue._handle(this._deferreds[i]);
135-
}
130+
self._state = 3;
131+
self._value = newValue;
132+
finale(self);
136133
return;
137134
} else if (typeof then === 'function') {
138-
doResolve(then.bind(newValue), this);
135+
doResolve(then.bind(newValue), self);
139136
return;
140137
}
141138
}
142-
this._state = 1;
143-
this._value = newValue;
144-
this._finale();
145-
};
146-
147-
Promise.prototype._reject = function (newValue) {
148-
this._state = 2;
149-
this._value = newValue;
150-
this._finale();
151-
};
152-
Promise.prototype._finale = function () {
153-
for (var i = 0; i < this._deferreds.length; i++)
154-
this._handle(this._deferreds[i]);
155-
this._deferreds = null;
156-
};
139+
self._state = 1;
140+
self._value = newValue;
141+
finale(self);
142+
}
157143

144+
function reject(self, newValue) {
145+
self._state = 2;
146+
self._value = newValue;
147+
finale(self);
148+
}
149+
function finale(self) {
150+
for (var i = 0; i < self._deferreds.length; i++) {
151+
handle(self, self._deferreds[i]);
152+
}
153+
self._deferreds = null;
154+
}
158155

159156
function Handler(onFulfilled, onRejected, promise){
160157
this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
@@ -173,14 +170,14 @@ function doResolve(fn, promise) {
173170
var res = tryCallTwo(fn, function (value) {
174171
if (done) return;
175172
done = true;
176-
promise._resolve(value);
173+
resolve(promise, value);
177174
}, function (reason) {
178175
if (done) return;
179176
done = true;
180-
promise._reject(reason);
181-
});
177+
reject(promise, reason);
178+
})
182179
if (!done && res === IS_ERROR) {
183180
done = true;
184-
promise._reject(LAST_ERROR);
181+
reject(promise, LAST_ERROR);
185182
}
186183
}

0 commit comments

Comments
 (0)