<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ES5-Promise</title>
</head>
<body>
<script>
// ES5 写法
function myPromise(constructor) {
let self = this;
self.status = "pending"; // 定义状态改变前的初始状态
self.value = undefined; // 定义状态为resolved的时候的状态
self.reason = undefined; // 定义状态为rejected的时候的状态
function resolve(value) {
// 两个==="pending",保证了了状态的改变是不不可逆的
if (self.status === "pending") {
self.value = value;
self.status = "resolved";
}
}
function reject(reason) {
// 两个==="pending",保证了了状态的改变是不不可逆的
if (self.status === "pending") {
self.reason = reason;
self.status = "rejected";
}
}
// 捕获构造异常
try {
constructor(resolve, reject);
} catch (e) {
reject(e);
}
}
myPromise.prototype.then = function (onFullfilled, onRejected) {
let self = this;
switch (self.status) {
case "resolved":
onFullfilled(self.value);
break;
case "rejected":
onRejected(self.reason);
break;
default:
}
};
// 测试实例
var p = new myPromise((resolve, reject) => {
resolve("success");
});
p.then((x) => {
console.log(1);
console.log(x);
});
p.then((x) => {
console.log(2);
console.log(x);
});
p.then((x) => {
console.log(3);
console.log(x);
});
</script>
</body>
</html>
ES6-Promise
const PENDING = 'pending';
const FULLFILLED = 'fullfilled';
const REJECTED = 'rejected';
function resolvePromise(promise2, x, resolve, reject) {
if (x === promise2) {
throw Error('不能返回自身');
}
if (x instanceof _Promise) {
if (x.status === PENDING) {
x.then(
y => resolvePromise(promise2, y, resolve, reject),
reject
)
} else if (x.status === FULLFILLED) {
resolve(x.value);
} else {
reject(x.value);
}
} else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
let then = null;
try {
then = x.then;
} catch (error) {
reject(error);
}
if (typeof then === 'function') {
let called = false;
try {
then.call(
x,
res => {
if (called) {
return;
}
called = true;
resolvePromise(promise2, res, resolve, reject);
},
error => {
if (called) {
return;
}
called = true;
reject(error);
}
)
} catch (error) {
if (called) {
return;
}
called = true;
reject(error);
}
} else {
resolve(x);
}
} else {
resolve(x);
}
}
class _Promise {
constructor(executor) {
this.status = PENDING;
this.value = null;
this.fullfilledCallbacks = [];
this.rejectedCallbacks = [];
try {
executor(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
resolve(value) {
if (this.status === PENDING) {
setTimeout(() => {
this.status = FULLFILLED;
this.value = value;
this.fullfilledCallbacks.forEach(callback => callback(value));
})
}
}
reject(reason) {
if (this.status === PENDING) {
setTimeout(() => {
this.status = REJECTED;
this.value = reason;
this.rejectedCallbacks.forEach(callback => callback(reason));
})
}
}
then(onFullfilled, onRejected) {
onFullfilled = typeof onFullfilled === 'function' ? onFullfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : error => { throw Error(error) }
let promise2 = new _Promise((resolve, reject) => {
if (this.status === PENDING) {
this.fullfilledCallbacks.push(() => {
try {
let x = onFullfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
this.rejectedCallbacks.push(() => {
try {
let x = onRejected(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
}
if (this.status === FULLFILLED) {
setTimeout(() => {
try {
let x = onFullfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
}
});
return promise2;
}
}