Promise
出现解决了js中的回调地狱的问题,使代码更简洁,是ES6中的规范和重要特性。它的使用很简单,但你知道它是怎么样实现的吗~~
如今咱们就来看一下Promise到底是怎么样实现的😄javascript
Promise
。看一下Promise
是如何使用的java
const promise = new Promise((resolve, reject) => {
try {
resolve('123');
} catch(err) {
reject('error');
}
});
promise
.then((msg) => {
console.log(msg)
})
复制代码
function
做为参数,function
中有resolve
和reject
两个方法。resolve
表明成功后返回的值,reject
表明拒绝返回的缘由根据Promise
的使用来建立一个叫MyPromise
的类git
/** * @params {function} callback 须要执行的业务方法 */
class MyPromise {
// 构造方法接收一个function
constructor(callback) {
callback(this.resolve, this.reject); // 调用此function
}
resolve = (value) => {} // callback中执行的resolve方法
reject = (reason) => {} // callback中执行的reject方法
}
// 测试
var test = new MyPromise((resolve, reject) => {
console.log('my promise is running!');
}) // 打印出 my promise is running!
复制代码
如今咱们建立的类已经能够执行传入的方法了,可是它传入的resolve
和reject
方法是有什么用的呢?
咱们接着看Promise规范 github
Promise
有三种状态 pending
(等待),fulfilled
(完成),rejected
(拒绝)。pending
时,Promise能够变为fulfilled
或rejected
状态fulfilled
时,Promise不能改变其状态;必须有值且不能改变rejected
时,Promise不能改变其状态;必须有拒绝的缘由且不能改变根据Promise
规则,接着写刚刚建立的类:面试
const stateArr = ['pending', 'fulfilled', 'rejected']; // 三种状态
/** * @params {function} callback 须要执行的业务方法 */
class MyPromise {
constructor(callback) {
this.state = stateArr[0]; // 当前状态
this.value = null; // 完成时的返回值
this.reason = null; // 失败缘由
callback(this.resolve, this.reject); // 调用此function
}
// callback中执行的resolve方法
resolve = (value) => {
// 判断状态是否须要是pending
if (this.state === stateArr[0]) {
this.state = stateArr[1]; // 更新状态为 fulfilled
this.value = value; // 写入最终的返回值
}
}
// callback中执行的reject方法
reject = (reason) => {
// 判断状态是否须要是pending
if (this.state === stateArr[0]) {
this.state = stateArr[2]; // 更新状态为 rejected
this.reason = reason; // 写入拒绝的缘由
}
}
}
复制代码
测试一下: 数组
resolve
后,状态变为
fulfilled,再调用
reject
时,状态和值都不会改变,这样符合Promise规范~~
咱们的MyPromise
写到这里,他已经能够实现更新状态和传值了,可是它的值怎么样输出给咱们的业务呢?
由Promise
的使用能够看到,它是经过then
方法来输出值的。then
是是一个必要的方法,看一下then
的规范:promise
then
方法去访问他的当前或最终的值或缘由then
方法接收两个参数 onFulilled
和onRejected
下面是关于onFulilled
和onRejected
的规范(部分)异步
onFulilled
和onRejected
二者都是一个可选的参数:
onFulilled
不是一个函数,它必须被忽视onRejected
不是一个函数,它必须被忽视onFulilled
是一个函数:
value
做为第一个参数onRejected
是一个函数:
reason
做为第一个参数onFulfilled
或onRejected
onFulfilled
和onRejected
必须是一个函数then
能够在同一个promise中屡次被调用then
必须返回一个promise
根据then函数的规则,咱们来设计这个then方法函数
const stateArr = ['pending', 'fulfilled', 'rejected']; // 三种状态
class MyPromise {
constructor(callback) {
this.state = stateArr[0]; // 当前状态
this.value = null; // 完成时的返回值
this.reason = null; // 失败缘由
callback(this.resolve, this.reject); // 调用此function
}
// callback中执行的resolve方法
resolve = (value) => {
// 判断状态是否须要是pending
if (this.state === stateArr[0]) {
this.state = stateArr[1]; // 更新状态为 fulfilled
this.value = value; // 写入最终的返回值
}
}
// callback中执行的reject方法
reject = (reason) => {
// 判断状态是否须要是pending
if (this.state === stateArr[0]) {
this.state = stateArr[2]; // 更新状态为 rejected
this.reason = reason; // 写入拒绝的缘由
}
}
// then方法
then = (onFulilled, onRejected) => {
// 判断onFulilled 和 onRejected是不是一个函数,若是不是函数则忽略它
onFulilled = typeof onFulilled === 'function' ? onFulilled : (value) => value;
onRejected = typeof onRejected === 'function' ? onRejected : (reason) => reason;
// 若是状态是fulfilled
if (this.state === stateArr[1]) {
// then返回的必须是一个promise
return new MyPromise((resolve, reject) => {
try {
const result = onFulilled(this.value); // 执行传入的onFulilled方法
// 若是onFulilled返回的是一个Promise,则调用then方法
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch(err) {
reject(err);
}
})
}
// 若是状态是rejected
if (this.state === stateArr[2]) {
// then返回的必须是一个promise
return new MyPromise((resolve, reject) => {
try {
const result = onRejected(this.reason); // 执行传入的onRejected方法
// 若是onRejected返回的是一个Promise,则调用then方法
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch(err) {
reject(err);
}
})
}
}
}
复制代码
测试一下:oop
成功返回:
失败返回:
至此,咱们的MyPromise
的已经基本能够运行了,可是如今有一个很严重的缺陷,若是遇到异步的请求时候,resolve
不能按上下文执行,这会致使then方法执行失败例如
var test = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(123);
}, 2000)
})
.then(msg => {
console.log(msg);
return 456;
})
复制代码
由于在调用then
方法的时候,promise
的状态尚未改变,而咱们的then
方法尚未处理pending状态的逻辑。 这致使执行异步方法的时候,then方法不会返回任何东西
好比,在上面的例子中,javscript已经把then
方法执行了,但setTimeout
中的方法还在eventloop
中等待执行。 这样须要作的是:
then
中的方法保存起来,等待resolve
或reject
执行后再调用刚刚保存的then
中的方法then
方法会被执行,因此须要用一个数据来保存这些方法// 在constructor中新增两个数组分别用于装then中的resolve和reject方法
constructor(callback) {
this.resolveArr = [];
this.rejectArr = [];
}
// 修改resolve方法
resolve = (value) => {
// 判断状态是否须要是pending
if (this.state === stateArr[0]) {
this.state = stateArr[1]; // 更新状态为 fulfilled
this.value = value; // 写入最终的返回值
this.resolveArr.forEach(fun => fun(value)) // 循环执行then已插入的resolve方法
}
}
// 修改reject方法
reject = (reason) => {
// 判断状态是否须要是pending
if (this.state === stateArr[0]) {
this.state = stateArr[1]; // 更新状态为 fulfilled
this.reason = reason; // 写入最终的返回值
this.rejectArr.forEach(fun => fun(reason)) // 循环执行then已插入的reject方法
}
}
// then方法中须要添加捕捉pending状态的逻辑
then = (onFulilled, onRejected) => {
// 若是状态为pending
if (this.state === stateArr[0]) {
return new Promise((resolve, reject) => {
// 插入成功时调用的函数
this.resolveArr.push((value) => {
try {
const result = onFulilled(value);
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch(err) {
reject(err);
}
})
// 插入失败时调用的函数
this.rejectArr.push((value) => {
try {
const result = onRejected(value);
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch(err) {
reject(err)
}
})
})
}
}
复制代码
写好了,测试一下~
new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(123);
}, 2000)
})
.then(msg => {
console.log(msg);
return new MyPromise((resolve, reject) => {
setTimeout(()=> {
resolve(456)
}, 2000);
})
})
.then(msg => {
console.log(msg);
})
复制代码
根据Promise规范实现的Promise
大体已经完成啦,最后咱们把Promise中实现的方法也补一下
// 在MyPromise原型中实现
class MyPromise {
// 调用then中的reject
catch = (reject) => {
this.then(null, reject);
}
}
复制代码
MyPromise.resolve = (value) => {
return new MyPromise((resolve, reject) => { resolve(value) });
}
复制代码
MyPromise.resolve = (reason) => {
return new MyPromise((resolve, reject) => { reject(reason) });
}
复制代码
all
,race
,finally(原型方法)
,其实都是根据Promise中的原型方法和Promise规则实现的,这里就不一一列举啦。须要了解的小伙伴能够自行去看const stateArr = ['pending', 'fulfilled', 'rejected']; // 三种状态
class MyPromise {
constructor(callback) {
this.state = stateArr[0]; // 当前状态
this.value = null; // 完成时的返回值
this.reason = null; // 失败缘由
this.resolveArr = [];
this.rejectArr = [];
callback(this.resolve, this.reject); // 调用此function
}
// callback中执行的resolve方法
resolve = (value) => {
// 判断状态是否须要是pending
if (this.state === stateArr[0]) {
this.state = stateArr[1]; // 更新状态为 fulfilled
this.value = value; // 写入最终的返回值
this.resolveArr.forEach(fun => fun(value)) // 循环执行then已插入的resolve方法
}
}
// callback中执行的reject方法
reject = (reason) => {
// 判断状态是否须要是pending
if (this.state === stateArr[0]) {
this.state = stateArr[1]; // 更新状态为 fulfilled
this.reason = reason; // 写入最终的返回值
this.rejectArr.forEach(fun => fun(reason)) // 循环执行then已插入的reject方法
}
}
// then方法
then = (onFulilled, onRejected) => {
// 判断onFulilled 和 onRejected是不是一个函数,若是不是函数则忽略它
onFulilled = typeof onFulilled === 'function' ? onFulilled : (value) => value;
onRejected = typeof onRejected === 'function' ? onRejected : (reason) => reason;
// 若是状态为pending
if (this.state === stateArr[0]) {
return new MyPromise((resolve, reject) => {
// 插入成功时调用的函数
this.resolveArr.push((value) => {
try {
const result = onFulilled(value);
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch(err) {
reject(err);
}
})
// 插入失败时调用的函数
this.rejectArr.push((value) => {
try {
const result = onRejected(value);
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch(err) {
reject(err)
}
})
})
}
// 若是状态是fulfilled
if (this.state === stateArr[1]) {
// then返回的必须是一个promise
return new MyPromise((resolve, reject) => {
try {
const result = onFulilled(this.value); // 执行传入的onFulilled方法
// 若是onFulilled返回的是一个Promise,则调用then方法
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch(err) {
reject(err);
}
})
}
// 若是状态是rejected
if (this.state === stateArr[2]) {
// then返回的必须是一个promise
return new MyPromise((resolve, reject) => {
try {
const result = onRejected(this.reason); // 执行传入的onRejected方法
// 若是onRejected返回的是一个Promise,则调用then方法
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch(err) {
reject(err);
}
})
}
}
// 调用then中的reject
catch = (reject) => {
this.then(null, reject);
}
}
MyPromise.resolve = (value) => {
return new MyPromise((resolve, reject) => { resolve(value) });
}
MyPromise.resolve = (reason) => {
return new MyPromise((resolve, reject) => { reject(reason) });
}
复制代码
此次咱们了解了promise是如何实现的:
从构造函数开始,到三种状态的实现,最后实现then方法一步步根据Promise规则
来实现Promise。了解完之后就能够在面试官面前手写一个Promise啦!😄