Если вы хотите передать свои функции кому-то еще, чтобы они вызывали с помощью
fn(this._resolve, this._reject);
и чтобы this
указывали на ваш объект обещания при их вызове, вам необходимо явно связать их:
fn(this._resolve.bind(this), this._reject.bind(this));
class Promisify {
constructor(fn) {
this.status = 0; // 0 = unfulfilled, 1 = resolved, 2 = rejected
this.result = undefined;
this.error = undefined;
this.thenFns = [];
this.catchFns = [];
this.finallyFn = undefined;
try {
fn(this._resolve.bind(this), this._reject.bind(this));
} catch (e) {
this._reject(e);
}
}
// public methods
then(fn) {
this.thenFns.push(fn);
this._doThen();
return this;
}
catch(fn) {
this.catchFns.push(fn);
this._doCatch();
return this;
};
finally(fn) {
this.finallyFn = fn;
return this;
}
// private methods
_doThen() {
if (this.status === 1) {
while(this.thenFns.length) {
this.thenFns.shift()(this.result);
}
}
}
_doCatch() {
if (this.status === 2) {
if (this.catchFns.length === 0) {
console.error('uncaught error')
}
while(this.catchFns.length) {
this.catchFns.shift()(this.error);
}
}
}
_resolve(r) {
if(this.status)
throw Error('cannot resolve, already handled');
this.status = 1;
this.result = r;
this._doThen();
}
_reject(e) {
if (this.status) throw Error('cannot reject, already handled');
this.status = 2;
this.error = e;
this._doCatch();
}
}
const demo = new Promisify((resolve, reject) => {
setTimeout(function() {
resolve('Howdy!')
}, 1000);
});
demo
.then(val => console.log("Demo Value in Then!!", val))
.catch(console.error) //Should throw an error.
.then(val => console.log("Second then!"))
.catch((err) => {
throw new Error('error', err);
})
.finally(val => console.log("Executed Finally"))