一、Promise/A+ 规范
需要前端最新进阶面试学习资料以及了解前端行业相关内容可以加交流群:954854084或者关注微信公众号:晨曦大前端 需要前端最新进阶面试学习资料以及了解前端行业相关内容可以加交流群:954854084或者关注微信公众号:晨曦大前端 需要前端最新进阶面试学习资料以及了解前端行业相关内容可以加交流群:954854084或者关注微信公众号:晨曦大前端
① Promise 是一个类
或者函数,内部拥有3个状态
,分别为pending(等待)、fulfilled(执行、完成)、rejected(拒绝、未完成)
。
默认为pending状态,即Promise对象刚创建的时候状态为pending
,并且pending状态可以转换fulfilled
或者rejected
。
fulfilled和rejected为最终的状态
,一旦变为fulfilled或者rejected,那么将无法转变为其他状态
。
② Promise需要对外提供一个then方法
。
promise.then(onFulfilled, onRejected)
如果可选参数onFulfilled和onRejected不为函数时应该被忽略
;
onFulfilled和onRejected函数都应该是异步执行
的;
当调用 onFulfilled 函数时,会将当前 Promise 的值作为参数传入,并且只能调用一次
;
当调用 onRejected 函数时,会将当前 Promise 的失败原因作为参数传入,并且只能调用一次
;
then函数的返回值仍然为Promise
,以便进行链式调用;
③ resolvePromise
then方法会创建并返回一个Promise对象,then中注册的回调函数会返回各种值,必须进行校验
。
then方法返回的promise不能与then中回调函数返回值x相等,否则需要抛出错误
;
如果是then回调函数返回值为一个非Promise对象
,则直接用then返回的promise对象的resolve方法
,resolve(x)即可。
如果then回调函数返回值x为一个Promise对象或者一个带then方法的对象或函数
,那么需要执行其then方法注册回调,拿到Promise或类Promise对象的值作为then返回的promise的值
,如果值仍然为Promise对象则需要进行递归操作
;
二、实现Promise
① 根据第一条规范,Promise是一个类或者函数,所以我们先将Promise定义成一个类
,同时内部有三个状态,我们将其定义为常量
。
var PENDING = "pending"; // 等待状态
var FULFILLED = "fulfilled"; // 执行、完成状态
var REJECTED = "rejected"; // 拒绝、未完成状态
class Promise {
constructor() {
this.state = PENDING; // Promise对象创建完成后默认为等待状态
}
}
② 我们在创建Promise的时候会传入一个函数
,该函数会在创建Promise对象的时候立即执行
,并且会接收两个参数
,分别用于执行
或拒绝
当前Promise对象,即修改当前Promise对象的状态
。Promise是用于处理异步的,所以在Promise状态变为完成的时候可能会接收到异步操作执行的结果,在Promise状态变为未完成的时候可能会接收到失败的原因
,所以Promise内部还需要保存异步操作的结果value、失败的原因reason
。
......
class Promise {
constructor(executor) { // 传入执行器函数
......
this.value = undefined; // 保存异步操作的结果
this.reason = undefined; // 保存失败的原因
const resolve = (value) => {
this.value = value;
this.state = FULFILLED; // 将Promise对象的状态改为完成状态
}
const reject = (reason) => {
this.reason = reason;
this.state = REJECTED; // 将Promise对象的状态改为未完成状态
}
try {
executor(resolve, reject); // 执行器由用户传入可能会发生错误,所以需要进行捕获
} catch(e) {
reject(e);
}
}
}
③ 这里还存在一个问题,就是Promise必须是单次执行的
,Promise的状态一旦从pending状态修改为fulfilled或者rejected,就不能再发生变化,从fulfilled变为fulfilled也不可以
,也就是说resolve或者reject只能执行一次
。所以我们需要对resolve和reject内部进行判断
,如果状态已经变化了则不再执行了,如:
......
class Promise {
constructor(executor) { // 传入执行器函数
......
const resolve = (value) => {
if (this.state === PENDING) { // 防止用户多次resolve,以第一次resolve为准
......
}
}
const reject = (reason) => {
if (this.state === PENDING) { // 防止用户多次reject
......
}
}
......
}
}
④ 给Promise添加一个then函数,then函数接收onFulfilled, onRejected两个函数作为参数
,分别用于处理Promise完成时和未完成时的回调函数,如果不是函数,则要进行初始化为一个函数,如:
class Promise {
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === "function"