先熟悉一下基本用法
- 前提,你要对js中的函数的用法,ES6新增的箭头函数和Promise的基本用法特别熟悉。
- 而且promise的设计在于状态的改变以及回调函数的传参。
- 先展示了一个最基本的用法
function fn1() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('定时器执行了');
resolve('我会把这句话传递给then')
}, 500)
}
)
}
fn1().then(res => {
console.log(res);
})
- 要清楚这几点,对后面写源码很重要
- Promise 接受1个参数,这个参数是一个函数(函数体)
- 函数体接受2个参数,可以叫他们回调函数, 而这个2个回调函数的函数体是在then中我们自己定义的,一般都喜欢写成箭头函数的形式(let resolve=>{ console.log(res);})
- 因此, Promise结构就变成了这样Promise(函数体(resolve,reject))
- 当我们new Promise之后,里面的函数体就会自动执行,函数体的调用写在Promise内部
- 执行之后会执行setTimeout和resolve,
- 对于resolve,声明放在函数体的参数里面,执行放在函数体的里面
- 当你完全理解了上面的含义之后,基本上就能写成一个简单的源码了,让我们来实现一下吧
简单的源码
//最基本的promise,不支持异步和链式调用
//一般我们把复用的变量定义在外面
const PENDING = "PENDING"
const RESOLVED = "RESOLVED"
const REJECTED = "REJECTED"
class Promise {
constructor(executor) {
//定义初始状态
this.status = PENDING
//定义成功和失败的回调函数的参数
this.value = undefined
this.reason = undefined
let resolve = (value) => {
//确保状态为PENGDING的时候才能被改变
if (this.status === PENDING) {
//改变状态
this.status = RESOLVED
//并且把resolve(value) 传给Promise.value = value
this.value = value
}
}
let reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED
this.reason = reason
}
}
//如果失败了就直接执行reject
try {
executor(resolve,reject)
} catch (e) {
reject(e)
}
}
//Promise的then方法
then(onfulfilled, onrejected) {
if (this.status === RESOLVED) {
//执行成功回调并传出去参数
onfulfilled(this.value)
}
if (this.status === REJECTED) {
onrejected(this.reason)
}
}
}
function fn1() {
return new Promise((resolve, reject) => {
console.log("我只想了")
resolve("我会把内容传递出去")
})
}
fn1().then((res) => {
console.log(res)
})
const PENDING = "PENDING"
const RESOLVED = "RESOLVED"
const REJECTED = "REJECTED"
class Promise {
constructor(executor) {
this.status = PENDING
this.value = undefined
this.reason = undefined
//添加异步任务的执行队列
this.resolveCb = []
this.rejectCb = []
let resolve = (value) => {
if (this.status === PENDING) {
this.status = RESOLVED
this.value = value
//如果状态改变了就执行对应的回调队列
this.resolveCb.forEach(fn=>{
fn()
})
}
}
let reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED
this.reason = reason
this.rejectCb.forEach(fn=>{
fn()
})
}
}
try {
executor(resolve,reject)
} catch (e) {
reject(e)
}
}
then(onfulfilled, onrejected) {
if (this.status === RESOLVED) {
onfulfilled(this.value)
}
if (this.status === REJECTED) {
onrejected(this.reason)
}
//此时fn1(),执行了马上执行then()
//但是因为异步关系resolve还没执行,
//因此把后续回调放在resolve中回调执行
if(this.status === PENDING){
//注意这里的回调添加
//为了把参数传过去,在函数体再添加函数的调用
this.resolveCb.push(()=>{
onfulfilled(this.value)
})
this.rejectCb.push(()=>{
onrejected(this.reason)
})
}
}
}
function fn1() {
return new Promise((resolve, reject) => {
setTimeout(()=>{
console.log('我执行了')
resolve('我会把这句话传递出去')
},500)
})
}
fn1().then((res) => {
console.log(res)
})