How do I implement promises by hand?
Implementing promises requires A full understanding of the Promise A+ specification, but from an overall implementation perspective, there are A few things to consider:
– Promise is essentially a state machine, and the states can only be the following three: This is a big pity. The change of the state is one-way and can only be realized from Pending -> depressing or Pending -> Rejected. The state change is irreversible
-then needs to support chained calls
class Promise {
callbacks = [];
state = ‘pending’; // Add state
value = null; // Save the result
constructor(fn) {
fn(this._resolve.bind(this), this._reject.bind(this));
}
then(onFulfilled, onRejected) {
return new Promise((resolve, reject) => {
this._handle({
onFulfilled: onFulfilled || null,
onRejected: onRejected || null,
resolve: resolve,
reject: reject
});
});
}
_handle(callback) {
if (this.state === ‘pending’) {
this.callbacks.push(callback);
return;
}
let cb = this.state === ‘fulfilled’ ? callback.onFulfilled : callback.onRejected;
if (! Cb) {// If nothing is passed in then
cb = this.state === ‘fulfilled’ ? callback.resolve : callback.reject;
cb(this.value);
return;
}
let ret = cb(this.value);
cb = this.state === ‘fulfilled’ ? callback.resolve : callback.reject;
cb(ret);
}
_resolve(value) {
if (value && (typeof value === ‘object’ || typeof value === ‘function’)) {
var then = value.then;
if (typeof then === ‘function’) {
then.call(value, this._resolve.bind(this), this._reject.bind(this));
return;
}
}
this.state = ‘fulfilled’; // Change the state
this.value = value; // Save the result
this.callbacks.forEach(callback => this._handle(callback));
}
_reject(error) {
this.state = ‘rejected’;
this.value = error;
this.callbacks.forEach(callback => this._handle(callback));
}
}
Promise.resolve
Promsie.resolve(value) Can convert any value to value. The state is a fulfilled Promise, but if the value passed in is itself a Promise, it will be returned as is.
Promise.resolve(value) {
if (value && value instanceof Promise) {
return value;
} else if (value && typeof value === ‘object’ && typeof value.then === ‘function’) {
let then = value.then;
return new Promise(resolve => {
then(resolve);
});
} else if (value) {
return new Promise(resolve => resolve(value));
} else {
return new Promise(resolve => resolve());
}
}
Promise.reject
Like promise.resolve (), promise.reject () instantiates a Promise in the Rejected state. But unlike promise.resolve (), if you pass a Promise object to promise.reject (), that object becomes the value of the new Promise.
Promise.reject = function(reason) {
return new Promise((resolve, reject) => reject(reason))
}
Promise.all
All Promsie passed in are fulfilled, and a new Promise consisting of their values is returned with the state of fulfilled;
As long as one Promise is Rejected, a new Promsie with the Rejected state is returned, and its value is the value of the first Rejected Promise.
As long as either Promise is pending, a new Promise in a pending state is returned;
Promise.all = function(promiseArr) {
let index = 0, result = []
return new Promise((resolve, reject) => {
promiseArr.forEach((p, i) => {
Promise.resolve(p).then(val => {
index++
result[i] = val
if (index === promiseArr.length) {
resolve(result)
}
}, err => {
reject(err)
})
})
})
}
Promise.race
Promise.race returns a new instance wrapped with the first Fulfilled or Rejected instance among all iterable instances.
Promise.race = function(promiseArr) {
return new Promise((resolve, reject) => {
promiseArr.forEach(p => {
Promise.resolve(p).then(val => {
resolve(val)
}, err => {
rejecte(err)
})
})
})
}
Today’s content to share here first, remember to like + follow ah ~