原生Promise底层是系统底层实现的微任务,我们通过代码无法实现,只能模拟宏任务去实现
/* 手写Promise */
const PENDING = 'padding';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MyPromise {
status = PENDING;
value = undefined;
reason = undefined;
successCallback = [];
failCallback = [];
constructor(executor) {
try {
executor(this.resolve, this.reject);
} catch (e) {
this.reject(e);
}
}
resolve = value => {
if (this.status !== PENDING) return;
this.status = FULFILLED;
this.value = value;
while (this.successCallback.length) {
this.successCallback.shift()();
}
};
reject = reason => {
if (this.status !== PENDING) return;
this.status = REJECTED;
this.reason = reason;
while (this.failCallback.length) {
this.failCallback.shift()();
}
};
then(
successCallback = value => value,
failCallback = reason => {
throw reason;
}
) {
let promiseThen = new MyPromise((resolve, reject) => {
const commonCallback = callback => {
setTimeout(() => {
try {
let thenResult = commonCallback(this.value);
resolvePromise(promiseThen, thenResult, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
};
if (this.status === FULFILLED) {
commonCallback(successCallback);
} else if (this.status === REJECTED) {
commonCallback(failCallback);
} else {
this.successCallback = [
...this.successCallback,
() => {
commonCallback(successCallback);
},
];
this.failCallback = [
...this.failCallback,
() => {
commonCallback(failCallback);
},
];
}
});
return promiseThen;
}
catch(failCallback) {
return this.then(undefined, failCallback);
}
finally(callback) {
return this.then(
value => {
return MyPromise.resolve(callback()).then(() => value);
},
reason => {
return MyPromise.resolve(callback()).then(() => {
throw reason;
});
}
);
}
static all(array) {
let result = [];
let order = 0;
return new MyPromise((resolve, reject) => {
const addData = (key, value) => {
result[key] = value;
order++;
if (order === array.length) {
resolve(result);
}
};
array.forEach((current, index) => {
if (current instanceof MyPromise) {
current.then(
value => addData(index, value),
reason => reject(reason)
);
} else {
addData(index, current);
}
});
});
}
static race(array) {
return new MyPromise((resolve, reject) => {
array.forEach(current => {
let value = current;
if (!(value instanceof MyPromise)) {
value = MyPromise.resolve(value);
}
value.then(
value => resolve(value),
reason => reject(reason)
);
});
});
}
static allSettled(array) {
let result = [];
let order = 0;
return new MyPromise(resolve => {
const addData = (key, value) => {
result[key] = value;
order++;
if (order === array.length) {
resolve(result);
}
};
array.forEach((current, index) => {
if (current instanceof MyPromise) {
current.then(
value => addData(index, value),
reason => addData(index, reason)
);
} else {
addData(index, current);
}
});
});
}
static any(array) {
let result = [];
let order = 0;
return new MyPromise((resolve, reject) => {
function addData(key, value) {
result[key] = value;
order++;
if (order === array.length) {
reject(result);
}
}
array.forEach((current, index) => {
if (current instanceof MyPromise) {
current.then(
value => resolve(value),
reason => addData(index, reason)
);
} else {
resolve(value);
}
});
});
}
static resolve(value) {
if (value instanceof MyPromise) return value;
return new MyPromise(resolve => resolve(value));
}
static reject(value) {
return new MyPromise((resolve, reject) => reject(value));
}
static try(fn) {
return new MyPromise(resolve => resolve(fn()));
}
}
function resolvePromise(promiseThen, value, resolve, reject) {
if (promiseThen === value) {
return reject(
new TypeError('Chaining cycle detected for promise #<Promise>')
);
}
if (value instanceof MyPromise) {
value.then(resolve, reject);
} else {
resolve(value);
}
}