目录
1.整体结构
1.1观察原生promise
- promise内部传入了一个参数且该参数是一个函数,并且该函数接收2个函数类型的参数(resolve,reject)
- 并且还可以在内部执行操作,执行resolve方法
- 还可以发现then方法属于promise的实例方法,所以应该在promise的原型对象(prototype)中有一个then方法,并且then方法接收2个函数类型的参数
let p = new Promise((resolve, reject) => {
resolve('OK');
});
p.then(
value => {
console.log(value); //ok
},
reason => {
console.log(reason);
}
)
1.2实现步骤
- 在promise构造函数内部定义一个excutor执行器函数
- 立即执行excutor执行器函数-----传入2个参数 resolve, reject (在内部定义好)
- 在promise的原型对象(prototype)上添加then方法---传入2个参数 onResolved,onRejected
/*
自定义promise模块: IIFE
*/
(function (window) {
/*
Promise构造函数
excutor: 执行器函数(同步执行)---传入2个参数 resolve,reject
*/
function Promise(excutor) {
function resolve(params){
}
function reject(params){
}
//立即同步执行excutor
excutor(resolve, reject)
}
/*
Promise原型对象的then()
*/
Promise.prototype.then = function (onResolved, onRejected) {
}
// 向外暴露Promise函数
window.Promise = Promise
})(window)
2.Promise的resolve,reject
一个 Promise
必然处于以下几种状态之一:
- 待定(pending):初始状态,既没有被兑现,也没有被拒绝。
- 已兑现(fulfilled):意味着操作成功完成。
- 已拒绝(rejected):意味着操作失败
resolev函数传入value参数,reject函数传入reason参数
注意:resolve函数与reject函数基本一致,先以resolve举例
1.调用resolve函数后,promise的状态会发生改变(变为resolved),并且它可以设置promise对象成功的结果
2.调用resolve函数
2.1设置初始值
- 设置resolve,reject函数的参数
- 定义三个常量状态 resolved(fulfilled) rejected pending
- 设置promise初始状态为pending
- 设置promise的结果值
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'
/*
Promise构造函数
excutor: 执行器函数(同步执行)---传入2个参数 resolve,reject
*/
function Promise(excutor) {
//将当前promise对象保存起来
const self=this
self.status = PENDING //给promise对象指定status属性,初始值为pending
self.data = undefined //给promise对象指定一个用于存储结果的数据的类型
function resolve(value) {
//1.修改对象的状态为resolved
self.status = RESOLVED
//2.保存value数据
self.data=value
}
function reject(reason) {
}
//立即同步执行excutor
excutor(resolve, reject)
}
2.2抛出异常及状态一旦修改就不能改变
let p = new Promise((resolve, reject) => {
reject('ok')
resolve('hhh')
});
console.log(p); //rejectde
根据上图原生的promise,和结果可以得出
- 当promise抛出异常后,也可以改变promise的状态值(rejected),而且抛出的error会作为promise的值
- promise的状态只能修改一次
function resolve(value) {
//如果当前状态不是pending, 直接结束
if (self.status !== PENDING) {
return
}
//1.修改对象的状态为resolved
self.status = RESOLVED
//2.保存value数据
self.data = value
}
function reject(reason) {
}
//立即同步执行excutor
try {
excutor(resolve, reject)
} catch (error) {
reject(error)
}
3.then方法的执行回调
then
方法可以接受两个回调函数作为参数。
第一个回调函数是Promise
对象的状态变为resolved
时调用,并输出结果值
第二个回调函数是Promise
对象的状态变为rejected
时调用,并输出结果值
在回调函数调用的时候会分成2种情况
1.在promise执行的是同步任务情况下,这个回调执行应该在then方法中执行
2.在promise执行的是异步任务情况下,这个回调执行应该先保存起来,在异步任务的时候执行
let p1 = new Promise((resolve, reject) => {
//第一种同步情况
resolve('同步')
});
let 2p = new Promise((resolve, reject) => {
//第二种同步情况
setTimeout(()=>{
resolve('异步')
})
});
3.1执行回调实现步骤
- 同步情况下需要判断promise的状态为什么,然后调用向对应的回调函数
- 异步情况下状态为pending,需要先保存回调函数,并等到promise状态判定完后进行执行,所以promise需要设定一个保存回调函数的数组(需要考虑promise可以执行多个异步回调),并且在resolve,reject方法里使用回调函数
/*
自定义promise模块: IIFE
*/
(function (window) {
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'
/*
Promise构造函数
excutor: 执行器函数(同步执行)---传入2个参数 resolve,reject
*/
function Promise(excutor) {
//将当前promise对象保存起来
const self = this
self.status = PENDING //给promise对象指定status属性,初始值为pending
self.data = undefined //给promise对象指定一个用于存储结果的数据的类型
self.callbacks = [] //每个数组元素的结构: { onResolved() {}, onRejected() {}}
function resolve(value) {
//如果当前状态不是pending, 直接结束
if (self.status !== PENDING) {
return
}
//1.修改对象的状态为resolved
self.status = RESOLVED
//2.保存value数据
self.data = value
//3.如果有待执行callback函数, 立即执行回调函数onResolved
self.callbacks.forEach(callback => {
callback.onResolved(value)
});
}
function reject(reason) {
//如果当前状态不是pending, 直接结束
if (self.status !== PENDING) {
return
}
//1.修改对象的状态为rejected
self.status = REJECTED
//2.保存value数据
self.data = reason
//3.如果有待执行callback函数, 立即执行回调函数onRejected
self.callbacks.forEach(callback => {
callback.onRejected(reason)
});
}
//立即同步执行excutor
try {
excutor(resolve, reject)
} catch (error) {
reject(error)
}
}
/*
Promise原型对象的then()
*/
Promise.prototype.then = function (onResolved, onRejected) {
const self = this
//根据状态调用回调函数
if (self.status === RESOLVED) { //resolved
onResolved(self.data)
} else if (self.status === REJECTED) { //rejected
onRejected(self.data)
} else { //pending
self.callbacks.push({
onRejected,
onResolved
})
}
}
4.then方法修改状态返回结果
let p = new Promise((resolve, reject) => {
//第一种
resolve('同步')
// setTimeout(()=>{
// resolve('异步')
// })
}).then(
value=>{
console.log('onResolved1 '+value);
return 2
},reason=>{
console.log(reason);
}
).then(
value=>{
console.log('onResolved2 '+value);
},reason=>{
console.log(reason);
}
)
由上图原生的promise可知
then方法返回的是一个promise ,并且返回promise的结果由onResolved/onRejected执行结果决定
大致分为:
- 抛出异常, 返回promise的结果为失败, reason为异常
- 返回的是promise, 返回promise的结果就是这个结果
- 返回的不是promise, 返回promise为成功, value就是返回值
4.1实现步骤(同步)
1.then方法返回的是一个promise,需要return一个promise
2返回promise的结果由onResolved/onRejected执行结果
if (self.status === RESOLVED) { //resolved
//返回promise的结果由onResolved/onRejected执行结果决定
// 1. 抛出异常, 返回promise的结果为失败, reason为异常
// 2. 返回的是promise, 返回promise的结果就是这个结果
// 3. 返回的不是promise, 返回promise为成功, value就是返回值
try {
const result = onResolved(self.data)
if (result instanceof Promise) { //第二种情况,返回的是promise
result.then(
value => resolve(vlaue),
reason => reject(reason)
)
} else { //第三种情况,不是promise
resolve(result)
}
} catch (error) {
reject(error)
}
} else if (self.status === REJECTED) { //rejected
try {
const result = onRejected(self.data)
if (result instanceof Promise) { //第二种情况,返回的是promise
result.then(
value => resolve(vlaue),
reason => reject(reason)
)
} else { //第三种情况,不是promise
resolve(result)
}
} catch (error) {
reject(error)
}
4.2实现步骤(异步)
else { //pending
self.callbacks.push({
onResolved(value){
try {
const result = onResolved(self.data)
if (result instanceof Promise) { //第二种情况,返回的是promise
result.then(
value => resolve(vlaue),
reason => reject(reason)
)
} else { //第三种情况,不是promise
resolve(result)
}
} catch (error) {
reject(error)
}
},
onRejected(reason){
try {
const result = onRejected(self.data)
if (result instanceof Promise) { //第二种情况,返回的是promise
result.then(
value => resolve(vlaue),
reason => reject(reason)
)
} else { //第三种情况,不是promise
resolve(result)
}
} catch (error) {
reject(error)
}
}
})
4.3封装函数及then方法回调的异步执行
1.封装函数
由同步和异步的修改状态返回结果来看,我们可以将他们封装成一个函数 handle
根据执行的结果改变return的promise的状态/数据 ,执行指定的回调函数
/*
执行指定的回调函数
根据执行的结果改变return的promise的状态/数据
*/
function handle(callback) {
//返回promise的结果由onResolved/onRejected执行结果决定
// 1. 抛出异常, 返回promise的结果为失败, reason为异常
// 2. 返回的是promise, 返回promise的结果就是这个结果
// 3. 返回的不是promise, 返回promise为成功, value就是返回值
try {
const result = callback(self.data)
if (result instanceof Promise) { //第二种情况,返回的是promise
result.then(
value => resolve(vlaue),
reason => reject(reason)
)
} else { //第三种情况,不是promise
resolve(result)
}
} catch (error) {
reject(error)
}
}
2.then方法回调的异步执行
let p = new Promise((resolve, reject) => {
// //第一种
// reject('同步')
setTimeout(()=>{
resolve('异步')
console.log('你好');
})
}).then(
value=>{
console.log('onResolved1 '+value);
return 2
},reason=>{
console.log(reason);
throw 2
}
).then(
value=>{
console.log('onResolved2 '+value);
},reason=>{
console.log(reason);
}
)
由上图可知,因为promise中的then方法的回调函数都是异步执行,我们需要在处理每个回调函数前加一个定时器
5.Promise构造函数以及then方法(总结)
/*
自定义promise模块: IIFE
*/
(function (window) {
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'
/*
Promise构造函数
excutor: 执行器函数(同步执行)---传入2个参数 resolve,reject
*/
function Promise(excutor) {
//将当前promise对象保存起来
const self = this
self.status = PENDING //给promise对象指定status属性,初始值为pending
self.data = undefined //给promise对象指定一个用于存储结果的数据的类型
self.callbacks = [] //每个数组元素的结构: { onResolved() {}, onRejected() {}}
function resolve(value) {
//如果当前状态不是pending, 直接结束
if (self.status !== PENDING) {
return
}
//1.修改对象的状态为resolved
self.status = RESOLVED
//2.保存value数据
self.data = value
//3.如果有待执行callback函数, 立即执行回调函数onResolved
if (self.callbacks.length > 0) {
setTimeout(() => {// 放入队列中执行所有成功的回调
self.callbacks.forEach(callback => {
callback.onResolved(value)
});
});
}
}
function reject(reason) {
//如果当前状态不是pending, 直接结束
if (self.status !== PENDING) {
return
}
//1.修改对象的状态为rejected
self.status = REJECTED
//2.保存value数据
self.data = reason
//3.如果有待执行callback函数, 立即执行回调函数onRejected
if (self.callbacks.length > 0) {
setTimeout(() => { // 放入队列中执行所有成功的回调
self.callbacks.forEach(callback => {
callback.onRejected(reason)
});
})
}
}
//立即同步执行excutor
try {
excutor(resolve, reject)
} catch (error) {
reject(error)
}
}
/*
Promise原型对象的then()
指定成功和失败的回调函数
返回一个新的promise
*/
Promise.prototype.then = function (onResolved, onRejected) {
const self = this
//返回一个新的promise
return new Promise((resolve, reject) => {
/*
执行指定的回调函数
根据执行的结果改变return的promise的状态/数据
*/
function handle(callback) {
//返回promise的结果由onResolved/onRejected执行结果决定
// 1. 抛出异常, 返回promise的结果为失败, reason为异常
// 2. 返回的是promise, 返回promise的结果就是这个结果
// 3. 返回的不是promise, 返回promise为成功, value就是返回值
try {
const result = callback(self.data)
if (result instanceof Promise) { //第二种情况,返回的是promise
result.then(
value => resolve(vlaue),
reason => reject(reason)
)
} else { //第三种情况,不是promise
resolve(result)
}
} catch (error) {
reject(error)
}
}
//根据状态调用回调函数
if (self.status === RESOLVED) { //resolved
// 立即异步执行成功的回调函数
setTimeout(() => {
handle(onResolved)
})
} else if (self.status === REJECTED) { //rejected
// 立即异步执行失败的回调函数
setTimeout(() => {
handle(onRejected)
})
} else { //pending
self.callbacks.push({
onResolved(value) {
handle(onResolved)
},
onRejected(reason) {
handle(onRejected)
}
})
}
})
}
// 向外暴露Promise函数
window.Promise = Promise
})(window)
6.promise的相关方法的实现
/*
Promise原型对象的catch()
指定失败的回调函数
返回一个新的promise对象
*/
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected)
}
/*
Promise函数对象的resolve方法
返回一个指定结果的成功的promise
*/
Promise.resolve = function (value) {
// 返回一个成功/失败的promise
return new Promise((resolve, reject) => {
// value是promise
if (value instanceof Promise) { // 使用value的结果作为promise的结果
value.then(resolve, reject)
} else { // value不是promise => promise变为成功, 数据是value
resolve(value)
}
})
}
/*
Promise函数对象的reject方法
返回一个指定reason的失败的promise
*/
Promise.reject = function (reason) {
// 返回一个失败的promise
return new Promise((resolve, reject) => {
reject(reason)
})
}
/*
Promise函数对象的all方法
返回一个promise, 只有当所有proimse都成功时才成功, 否则只要有一个失败的就失败
*/
Promise.all = function (promises) {
// 用来保存所有成功value的数组
const values = new Array(promises.length)
// 用来保存成功promise的数量
let resolvedCount = 0
// 返回一个新的promise
return new Promise((resolve, reject) => {
// 遍历promises获取每个promise的结果
promises.forEach((p, index) => {
Promise.resolve(p).then(
value => {
resolvedCount++ // 成功的数量加1
// p成功, 将成功的vlaue保存vlaues
// values.push(value)
values[index] = value
// 如果全部成功了, 将return的promise改变成功
if (resolvedCount===promises.length) {
resolve(values)
}
},
reason => { // 只要一个失败了, return的promise就失败
reject(reason)
}
)
})
})
}
/*
Promise函数对象的race方法
返回一个promise, 其结果由第一个完成的promise决定
*/
Promise.race = function (promises) {
// 返回一个promise
return new Promise((resolve, reject) => {
// 遍历promises获取每个promise的结果
promises.forEach((p, index) => {
Promise.resolve(p).then(
value => {// 一旦有成功了, 将return变为成功
resolve(value)
},
reason => { // 一旦有失败了, 将return变为失败
reject(reason)
}
)
})
})
}