Promise初始结构搭建
let p = new Promise ( ( resolve, reject ) => {
resolve ( 'OK' )
} )
p. then ( value => {
console. log ( value) ;
} , reason => {
console. warn ( reason) ;
} )
参考原始Promise对象中的结构,构造函数Promise
中包含一个执行器函数,原型上有then
方法,该方法接收两个函数参数 搭建好结构:
function myPromise ( executor ) {
}
myPromise. prototype. then = function ( onResolved, onRejected ) {
}
resolve与reject结构搭建
考虑到Promise对象
中的执行器函数是同步调用 的,并且具有两个函数参数(resolve, reject)
,需要对这两个函数在构造函数内部进行声明,考虑到原始构造中函数有传递参数值data
function myPromise ( executor ) {
function resolve ( data ) {
}
function reject ( data ) {
}
executor ( resolve, reject)
}
resolve与reject代码实现
promise状态会发生改变 设置成功的结果
为了给实例对象表示状态的转变以及数据的传输,需要设定两个值
function myPromise ( executor ) {
this . promiseState = 'pendinng'
this . promiseResult = null
function resolve ( data ) {
this . promiseState = 'fulfilled'
this . promiseResult = data
}
若直接如上方式书写,this的指向会指向window而非实例对象 因此需要保存实例对象的this值
function myPromise ( executor ) {
this . promiseState = 'pendinng'
this . promiseResult = null
const self = this
function resolve ( data ) {
self. promiseState = 'fulfilled'
self. promiseResult = data
}
}
function reject ( data ) {
self. promiseState = 'rejected'
self. promiseResult = data
}
throw抛出异常改变状态
let p = new Promise ( ( resolve, reject ) => {
throw "error"
} )
console. log ( p)
如何处理throw
?想到try..catch..
方法 往哪里加try..catch..
?考虑到是在执行器函数内部执行,通过catch
捕捉的throw
后,调用reject
函数修改状态
try {
executor ( resolve, reject)
} catch ( error) {
reject ( error)
}
Promise对象状态只能修改一次
由于状态只能改变一次,且只能由pendding
状态变为其他,故要进行判断
function resolve ( data ) {
if ( self. promiseState !== 'pendinng' ) return ;
self. promiseState = 'fulfilled'
self. promiseResult = data
}
function reject ( data ) {
if ( self. promiseState !== 'pendinng' ) return ;
self. promiseState = 'rejected'
self. promiseResult = data
}
then方法执行回调
myPromise. prototype. then = function ( onResolved, onRejected ) {
if ( this . promiseState === 'fulfilled' ) {
onResolved ( this . promiseResult)
}
if ( this . promiseState === 'rejected' ) {
onRejected ( this . promiseResult)
}
}
异步任务then回调的执行
若异步执行回调函数,then方法不会执行,由于异步,状态还未发生改变,便执行then方法
let p = new myPromise ( ( resolve, reject ) => {
setTimeout ( ( ) => {
resolve ( 'OK' )
} , 1000 ) ;
} )
故还需要进行判断,真正调用回调函数的时机是在(resolve, reject)
中,我们需要在then方法中保存回调函数,在Promise
对象中声明一个属性保存成功和失败的回调函数
function myPromise ( executor ) {
this . promiseState = 'pendinng'
this . promiseResult = null
this . callback = { }
在then方法中判断,一旦promise 是pendding状态,将回调函数保存到该属性中
myPromise. prototype. then = function ( onResolved, onRejected ) {
if ( this . promiseState === 'fulfilled' ) {
onResolved ( this . promiseResult)
}
if ( this . promiseState === 'rejected' ) {
onRejected ( this . promiseResult)
}
if ( this . promiseState === 'pendinng' ) {
this . callback = {
onResolved,
onRejected
}
}
}
然后在promise对象中对应的(resolve, reject)
函数里面调用
function resolve ( data ) {
if ( self. promiseState !== 'pendinng' ) return ;
self. promiseState = 'fulfilled'
self. promiseResult = data
if ( self. callback. onResolved) {
self. callback. onResolved ( data)
}
}
指定多个回调的实现
上述方法修改回调函数会存在一个问题,若是后面新增的then方法会将之前的回调函数覆盖
p. then ( value => {
console. log ( value) ;
} , reason => {
console. warn ( reason) ;
} )
p. then ( value => {
alert ( value) ;
} , reason => {
alert ( reason) ;
} )
更改:用数组 保存回调函数,在(resolve, reject)
函数遍历执行
this . callbacks = [ ]
-- -- -- -- -- -- . then-- -- -- -- -- -
if ( this . promiseState === 'pendinng' ) {
this . callbacks. push ( {
onResolved,
onRejected
} )
}
-- -- -- -- -- - ( resolve, reject) -- -- -- -- -- --
self. callbacks. forEach ( item => {
item. onResolved ( data)
} )
同步任务下修改状态then方法结果返回
由于then方法的返回值是一个promise对象,由参数函数的状态及值决定
const result = p. then ( value => {
console. log ( value) ;
} , reason => {
console. warn ( reason) ;
} )
console. log ( result) ;
首先then方法实现的是一个promise对象,然后考虑到回调函数返回的是promise对象还是值还是抛出错误
myPromise. prototype. then = function ( onResolved, onRejected ) {
return new myPromise ( ( resolve, reject ) => {
if ( this . promiseState === 'fulfilled' ) {
try {
let result = onResolved ( this . promiseResult)
if ( result instanceof myPromise ) {
result. then ( v => {
resolve ( v)
} , r => {
reject ( r)
} )
} else {
resolve ( result)
}
} catch ( error) {
reject ( error)
}
}
... reject
}
异步任务下修改状态then方法结果返回
若是异步,由于状态仍然是pendding,进入到此时的then方法中,并没有调用resolve或者reject函数,因此返回的结果promise仍然是pendding状态
const self = this
if ( this . promiseState === 'pendinng' ) {
this . callbacks. push ( {
onResolved : function ( ) {
try {
let result = onResolved ( this . promiseResult)
if ( result instanceof myPromise ) {
result. then ( v => {
resolve ( v)
} , r => {
reject ( r)
} )
} else {
resolve ( result)
}
} catch ( error) {
reject ( error)
}
} ,
onRejected : function ( ) {
}
then方法的完善和优化
function callback ( type ) {
try {
let result = type ( self. promiseResult)
if ( result instanceof myPromise ) {
result. then ( v => {
resolve ( v)
} , r => {
reject ( r)
} )
} else {
resolve ( result)
}
} catch ( error) {
reject ( error)
}
}
-- -- -- -- -- -- - then return -- -- -- -- -- -- -- -
if ( this . promiseState === 'fulfilled' ) {
callback ( onResolved)
}
if ( this . promiseState === 'rejected' ) {
callback ( onRejected)
}
then方法回调的异步执行
let p = new myPromise ( ( resolve, reject ) => {
resolve ( 'OK' )
console. log ( 111 ) ;
} )
p. then ( value => {
console. log ( 222 ) ;
} )
console. log ( 333 ) ;
需要在then方法成功和失败的状态下,以及promise对象中的resolve和reject的回调函数数组,用定时器包裹
-- -- -- -- -- -- -- -- - . then -- -- -- -- -- -- -- -- --
if ( this . promiseState === 'fulfilled' ) {
setTimeout ( ( ) => {
callback ( onResolved)
} ) ;
}
setTimeout ( ( ) => {
self. callbacks. forEach ( item => {
item. onResolved ( data)
} )
} ) ;
catch方法-异常穿透与值传递
p. catch ( reason => {
console. warn ( reason) ;
} )
myPromise. prototype. catch = function ( onRejected ) {
return this . then ( undefined , onRejected)
}
实现异常穿透和值传递,让then方法中的两个函数参数是可传可不传的
if ( typeof onResolved!== 'function' ) {
onResolved = value => value
}
if ( typeof onRejected !== 'function' ) {
onRejected = reason => {
throw reason
}
}
promise函数上resolve方法的封装
const p = Promise. resolve ( 'OK' )
myPromise. resolve = function ( value ) {
return new myPromise ( ( resolve, reject ) => {
if ( value instanceof myPromise ) {
value. then ( v => {
resolve ( v)
} , r => {
reject ( r)
} )
} else {
resolve ( value)
}
} )
}
promise函数上reject方法的封装
myPromise. resolve = function ( reason ) {
return new myPromise ( ( resolve, reject ) => {
reject ( reason)
} )
}
promise函数上all方法的封装
返回promise对象,参数为promise组成的数组,结果为成功结果的数组,有一个失败就失败
myPromise. all = function ( promises ) {
return new myPromise ( ( resolve, reject ) => {
let count = 0
let res = [ ]
for ( let i = 0 ; i < promises. length; i++ ) {
promises[ i] . then ( v => {
count++
res[ i] = v
if ( count === promises. length) resolve ( res) ;
} , r => {
reject ( r)
} )
}
} )
}
promise函数上race方法的封装
myPromise. race = function ( promises ) {
return new myPromise ( ( resolve, reject ) => {
for ( let i = 0 ; i < promises. length; i++ ) {
promises[ i] . then ( v => {
resolve ( v) ;
} , r => {
reject ( r)
} )
}
} )
}
class版本实现
class Promise {
constructor ( executor ) {
this . PromiseState = 'pending' ;
this . PromiseResult = null ;
this . callbacks = [ ] ;
let resolve = ( data ) => {
if ( this . PromiseState !== 'pending' ) return ;
this . PromiseState = 'fulfilled' ;
this . PromiseResult = data;
setTimeout ( ( ) => {
this . callbacks. forEach ( item => {
item. onResolved ( data) ;
} ) ;
} ) ;
}
let reject = ( data ) => {
if ( this . PromiseState !== 'pending' ) return ;
this . PromiseState = 'rejected' ;
this . PromiseResult = data;
setTimeout ( ( ) => {
this . callbacks. forEach ( item => {
item. onRejected ( data) ;
} ) ;
} ) ;
}
try {
executor ( resolve, reject) ;
} catch ( e) {
reject ( e) ;
}
}
then ( onResolved, onRejected ) {
if ( typeof onRejected !== 'function' ) {
onRejected = reason => {
throw reason;
}
}
if ( typeof onResolved !== 'function' ) {
onResolved = value => value;
}
return new Promise ( ( resolve, reject ) => {
let callback = ( type ) => {
try {
let result = type ( this . PromiseResult) ;
if ( result instanceof Promise ) {
result. then ( v => {
resolve ( v) ;
} , r => {
reject ( r) ;
} )
} else {
resolve ( result) ;
}
} catch ( e) {
reject ( e) ;
}
}
if ( this . PromiseState === 'fulfilled' ) {
setTimeout ( ( ) => {
callback ( onResolved) ;
} ) ;
}
if ( this . PromiseState === 'rejected' ) {
setTimeout ( ( ) => {
callback ( onRejected) ;
} ) ;
}
if ( this . PromiseState === 'pending' ) {
this . callbacks. push ( {
onResolved : function ( ) {
callback ( onResolved) ;
} ,
onRejected : function ( ) {
callback ( onRejected) ;
}
} ) ;
}
} )
}
catch ( onRejected) {
return this . then ( undefined , onRejected) ;
}
static resolve ( value ) {
return new Promise ( ( resolve, reject ) => {
if ( value instanceof Promise ) {
value. then ( v => {
resolve ( v) ;
} , r => {
reject ( r) ;
} )
} else {
resolve ( value) ;
}
} ) ;
}
static reject ( reason ) {
return new Promise ( ( resolve, reject ) => {
reject ( reason) ;
} ) ;
}
static all ( promises ) {
return new Promise ( ( resolve, reject ) => {
let count = 0 ;
let arr = [ ] ;
for ( let i = 0 ; i < promises. length; i++ ) {
promises[ i] . then ( v => {
count++ ;
arr[ i] = v;
if ( count === promises. length) {
resolve ( arr) ;
}
} , r => {
reject ( r) ;
} ) ;
}
} ) ;
}
static race ( promises ) {
return new Promise ( ( resolve, reject ) => {
for ( let i = 0 ; i < promises. length; i++ ) {
promises[ i] . then ( v => {
resolve ( v) ;
} , r => {
reject ( r) ;
} )
}
} ) ;
}
}