手动实现Promise
什么是Promise
Promise 是异步编程的一种解决方案,使用Promise对象可以将异步操作以同步操作的流程表达出来,同时可以解决回调地狱的问题
- 一个Promise构造函数
// 下面这行代码表示创建了一个【形式上的】异步操作 具体是干什么的并不知道
const p = new Promise()
// 在new promise 时传入functon函数 在function中可以执行具体的异步操作
// 这种格式叫做创建了一个具体的异步操作
const p = new Promise(function(){
// 在这个function中 可以写具体的异步操作
// 如 读文件 或者发送Ajax
})
- Promise对象的使用
let promise = new Promise(function (reslove, reject) {
if (true) {
reslove("resolve函数传递的数据");// 如果执行reslove函数,那么Promise对象将从Pending状态转换为Resolved状态
} else {
reject("reject函数传递的数据");// 如果执行reslove函数,那么Promise对象将从Pending状态转换为Rejected状态
}
/*
因为Promise对象只要new 就会立即执行,那么它执行后的状态也就会返回给实例
在实例的then方法中,会监听Promise返回的状态,如果是Resolved状态,就会执行第一个参数(回调函数),
如果是Rejected状态,就会执行第二个参数(回调函数)
如果调用resolve或reject函数时带有参数,那么这些参数会传递给回调函数,也就是实例.then()中的两个回调函数
*/
})
promise.then(function (data) {
console.log(data + " Resolved状态的回调函数执行了");
}, function (data) {
console.log(data + " Reject状态的回调执行了");
})
var p1 = new Promise(function (resolve, reject) { })
var p2 = new Promise(function (resolve, reject) {
resolve();
})
p2.then(function () {
return "第一个回调";
}).then(function (data) {
console.log(data);
})
- Promise.prototype.then() 方法
连续调用then方法:then方法被调用后会返回一个新的promise对象,并且将返回结果(如果有return)作为参数,传递给下一个回调函数
p2.then(function () {
return "第一个回调";
}).then(function (data) {
console.log(data);
})
手动实现Promise构造函数
//1.定义三种状态
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'
function MyPromise(fn) {
this.status = PENDING;
this.value = undefined; // 保存resolved或者rejected函数传入的参数
this.resolvedCallbacks = []; // 里面保存的的是字符串"() => { onFulfilled(this.value)"
this.rejectedCallbacks = [];
const resolved = (value) => {
// 这里获取到的value参数就是new MyPromise 时执行传入的函数中执行resolve函数传来的参数
if (this.status == PENDING) {
console.log("resolved执行了");
this.status = RESOLVED;
this.value = value;
this.resolvedCallbacks.forEach(cb => cb());
}
}
const rejected = (value) => {
if (this.status == PENDING) {
console.log("rejected执行了");
this.status = REJECTED;
this.value = value;
this.rejectedCallbacks.forEach(cb => cb())
}
}
try {
fn(resolved, rejected);
} catch (e) {
console.log(e);
rejected(e);
}
}
手动实现Promise.prototype.then()方法
简易版then方法,不能实现连续then
MyPromise.prototype.then = function (onFulfilled, onRejected) {
const that = this;
onFulfilled = typeof onFulfilled == "function" ? onFulfilled : v => v;
onRejected = typeof onRejected == "function" ? onRejected : r => { throw r };
if (that.status === RESOLVED) {// 如果new MyPromise 的时候执行了resolved函数,那么应该执行then中的第一个回调函数
onFulfilled(that.value);
}
if (that.status === REJECTED) {// 如果new MyPromise 的时候执行了rejected函数,那么应该执行then中的第二个回调函数
onRejected(that.value);
}
// 如果是异步调用的then方法,就先不执行函数,先把函数存到数组中
// 当 status 变化后,再遍历数组,执行函数
if (that.status === PENDING) {
that.resolvedCallbacks.push(() => { onFulfilled(that.value) })
that.rejectedCallbacks.push(() => { onRejected(that.value) })
}
}
增强版的then函数,可以链式调用
MyPromise.prototype.then = function (onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled == "function" ? onFulfilled : v => v;
onRejected = typeof onRejected == "function" ? onRejected : r => { throw r };
let promise2 = new MyPromise((resolve, reject) => {
if (this.status === RESOLVED) {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(x, promise2, resolve, reject);
} catch (e) {
reject(e);
}
}, 0)
return;
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.value);
resolvePromise(x, promise2, resolve, reject);
} catch (e) {
reject(e);
}
}, 0)
}
// 如果是异步调用的then方法,就先不执行函数,先把函数存到数组中
// 当 status 变化后,再遍历数组,执行函数
if (this.status === PENDING) {
// 异步,就先不执行函数,先把函数存储到数组中
// 当 status 变化后,在遍历数组,执行函数
this.resolvedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(x, promise2, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
this.rejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.value);
resolvePromise(x, promise2, resolve, reject);
} catch (e) {
reject(e);
}
}, 0)
});
}
})
return promise2;
}
resolvePromise方法的实现
const resolvePromise = (x, promise2, resolve, reject) => {
if (x === promise2) {
return reject(new TypeError("then回调的返回值和它本身相等,陷入死循环"))
}
if ((typeof x === "object" && x !== null) || typeof x === "function") {
try {
let then = x.then;
if (typeof then === "function") {// 如果x对象或方法中的then属性也是一个方法,就继续执行这个方法
then.call(x, y => {
resolvePromise(y, promise2, resolve, reject);
}, err => {
reject(err);
})
} else { // 对象或者函数中没有 then 方法,就按照普通值处理
resolve(x);
}
} catch (e) {
reject(e);
}
} else {
resolve(x); // x 不是对象或方法,是一个普通值
}
}
测试
// 下面都是测试
let promise = new MyPromise(function (reslove, reject) {
if (true) {
reslove("resolve函数传递的数据");// 如果执行reslove函数,那么Promise对象将从Pending状态转换为Resolved状态
} else {
reject("reject函数传递的数据");// 如果执行reslove函数,那么Promise对象将从Pending状态转换为Rejected状态
}
})
// console.log(promise);
promise.then(function (data) {
console.log(data + " Resolved状态的回调函数执行了");
}, function (data) {
console.log(data + " Reject状态的回调执行了");
}).then(function () {
console.log("另一个then函数");
})
//输出:
//resolved执行了
//resolve函数传递的数据 Resolved状态的回调函数执行了
//resolved执行了
//另一个then函数
//resolved执行了