Promise用的很多,比较熟悉Promise的使用,一直没有思考过Promise的实现,今天尝试着写一个完整的Promise。
第一部分 - 简单的Promise实现
function Promise(fn) {
// 存放onFulfilled队列
let callback = [];
fn(reslove);
function reslove(value) {
callback.forEach(fn => fn(value))
}
this.then = function (fn) {
callback.push(fn)
};
}
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('hello')
}, 100);
})
p.then(res => {
console.log(res)
})
// hello
- 创建Promise的实例传入一个函数,将resolve作为函数参数,异步执行后的结果作为resolve的参数。then函数在异步执行前已经执行。
第二部分 - Promise链式调用
- 在then函数里添加一个return Promise实例
function Promise(fn) {
let callback = [];
fn(reslove);
function reslove(value) {
callback.forEach(fn => fn(value))
}
// 在then函数加一个return就可以了
this.then = function (fn) {
callback.push(fn)
return this
};
}
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('hello')
}, 100);
})
p.then(res => {
console.log(res)
}).then(res => {
console.log(res)
}).then(res => {
console.log(res)
})
// hello hello hello
- 保证链式调用返回的是相同的value,如果不同的需要做不同的处理
第三部分 - 同步异步
- 创建Promise的实例传入的函数内部是一个异步函数,如果是同步函数导致then函数不执行,因为callback是一个空数组,onfulfilled函数还没有注册。
- 为了解决同步异步问题,增加一个状态管理
- 待定(pending): 初始状态,既没有被兑现,也没有被拒绝。
- 已兑现(fulfilled): 意味着操作成功完成。
- 已拒绝(rejected): 意味着操作失败。
const PENDING = 0
const FULFILLED = 1
const REJECTED = 2
function Promise(fn) {
this.handlers = [];
this.state = PENDING
this.value = null
fn(reslove.bind(this));
function reslove(value) {
this.state = FULFILLED
this.value = value
this.handlers.forEach(fn => fn(value))
}
this.then = function (onfulfilled) {
if (this.state === PENDING) {
this.handlers.push(onfulfilled)
} else {
onfulfilled(this.value)
}
return this
};
}
let p = new Promise((resolve, reject) => {
resolve('hello')
})
p.then(res => {
console.log(res)
})
- 如果是同步执行直接,直接把value值给到传入到then的函数。反之,handlers队列不为空。
第四部分 - 真正的Promise链式调用
- 第二部分的链式调用在层层递进的过程中返回都是相同的value,如果每个then返回不同的Promise,这就不是我们希望看到的效果。真正的链式调用应该是返回一个新的Promise实例,这里我们可以通过then函数返回一个新的Promise实例。
const PENDING = 0
const FULFILLED = 1
const REJECTED = 2
function Promise(fn) {
this.handlers = [];
this.state = PENDING
this.value = null
fn(reslove.bind(this));
function reslove(value) {
// 如果接受到的value是一个Promise实例,未作处理
this.state = FULFILLED
this.value = value
// 执行handlers队列函数
this.handlers.forEach(fn => this.handle(fn))
}
this.handle = (fn) => {
// 在resolve之前添加到handlers队列
if (this.state === PENDING) {
this.handlers.push(fn)
return
}
// then函数没有传递任何参数
//这个部分意义不大,但是要做处理,很少有then为空的情况
if (!fn.onfulfilled) {
fn.resolve(this.value)
return
}
// 真正的链式调用返回的ret是一个Promise实例
// 同步和异步执行直接把value给到then传入函数
let ret = fn.onfulfilled(this.value);
// 这里把返回的Promise实例给到resolve函数
fn.resolve(ret)
}
this.then = function (onfulfilled) {
// 链式调用,返回一个新的Promise实例
return new Promise((resolve, reject) => {
this.handle({
onfulfilled,
resolve
})
})
};
}
let p = () => {
return new Promise((resolve, reject) => {
resolve('hello')
})
}
p().then(res => {
console.log(res)
})
// hello
- 上图的then函数返回一个Promise的实例,then和resolve共用一个handle函数。但是如果多个then函数返回Promise实例还是不支持。这里需要在resolve做个处理。
在resolve中处理传入的Promise实例的参数
const PENDING = 0
const FULFILLED = 1
const REJECTED = 2
function Promise(fn) {
this.handlers = [];
this.state = PENDING
this.value = null
fn(resolve.bind(this));
function resolve(value) {
// 如果接受到的value是一个Promise实例
const nameList = ['object', 'function']
if (value && nameList.includes(typeof value)) {
const then = value.then
if (nameList.includes(typeof then)) {
then.call(value, resolve.bind(this))
return
}
}
this.state = FULFILLED
this.value = value
// 执行handlers队列函数
this.handlers.forEach(fn => this.handle(fn))
}
this.handle = (fn) => {
// 在resolve之前添加到handlers队列
if (this.state === PENDING) {
this.handlers.push(fn)
return
}
// then函数没有传递任何参数
if (!fn.onfulfilled) {
fn.resolve(this.value)
return
}
// 真正的链式调用返回的ret是一个Promise实例
// 同步和异步执行直接把value给到then传入函数
let ret = fn.onfulfilled(this.value);
// 这里把返回的Promise实例给到resolve函数
fn.resolve(ret)
}
this.then = function (onfulfilled) {
// 链式调用,返回一个新的Promise实例
return new Promise((resolve, reject) => {
this.handle({
onfulfilled,
resolve
})
})
};
}
let p = () => {
return new Promise((resolve, reject) => {
resolve('hello')
})
}
let p1 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('hello1')
}, 100);
})
}
let p2 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('hello2')
}, 100);
})
}
let p3 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('hello3')
}, 100);
})
}
p().then(res => {
console.log(res)
return p1()
}).then(res => {
console.log(res);
return p2()
}).then(res => {
console.log(res);
return p3()
}).then(res => {
console.log(res);
})
- Promise的实现链式调用,也就是纵向发展,使得callback hell现象不复存在。
网友评论