const isFunction = variable => typeof variable === 'function' ; const PENDING = 'pending' ; const FULFILLED = 'fulfilled' ; const REJECTED = 'rejected' ; class MyPromise { constructor ( handle ) { try { handle ( this . _resolve , this . _reject ) ; } catch ( err ) { this . _reject ( err ) ; } } private _status : string = PENDING ; private _value : string | undefined = undefined ; private _rejectedQueues : any = [ ] ; private _fulfilledQueues : any = [ ] ; private _resolve = val => { const run = ( ) => { if ( this . _status !== PENDING ) return ; this . _status = FULFILLED ; const runFulfilled = value => { let cb ; while ( ( cb = this . _fulfilledQueues . shift ( ) ) ) { cb ( value ) ; } } ; const runRejected = error => { let cb ; while ( ( cb = this . _rejectedQueues . shift ( ) ) ) { cb ( error ) ; } } ; if ( val instanceof MyPromise ) { val . then ( value => { this . _value = value ; runFulfilled ( value ) ; } , err => { this . _value = err ; runRejected ( err ) ; } ) ; } else { this . _value = val ; runFulfilled ( val ) ; } } ; setTimeout ( run ) ; } ; private _reject = err => { if ( this . _status !== PENDING ) return ; const run = ( ) => { this . _status = REJECTED ; this . _value = err ; let cb ; while ( ( cb = this . _rejectedQueues . shift ( ) ) ) { cb ( err ) ; } } ; setTimeout ( run ) ; } ; then ( onFulfilled ? , onRejected ? ) { const { _value , _status } = this ; return new MyPromise ( ( onFulfilledNext , onRejectedNext ) => { const fulfilled = value => { try { if ( ! isFunction ( onFulfilled ) ) { onFulfilledNext ( value ) ; } else { const res = onFulfilled ( value ) ; if ( res instanceof MyPromise ) { res . then ( onFulfilledNext , onRejectedNext ) ; } else { onFulfilledNext ( res ) ; } } } catch ( err ) { onRejectedNext ( err ) ; } } ; const rejected = error => { try { if ( ! isFunction ( onRejected ) ) { onRejectedNext ( error ) ; } else { const res = onRejected ( error ) ; if ( res instanceof MyPromise ) { res . then ( onFulfilledNext , onRejectedNext ) ; } else { onFulfilledNext ( res ) ; } } } catch ( err ) { onRejectedNext ( err ) ; } } ; switch ( _status ) { case PENDING : this . _fulfilledQueues . push ( fulfilled ) ; this . _rejectedQueues . push ( rejected ) ; break ; case FULFILLED : fulfilled ( _value ) ; break ; case REJECTED : rejected ( _value ) ; break ; } } ) ; } catch ( onRejected ) { return this . then ( undefined , onRejected ) ; } finally ( cb ) { return this . then ( value => MyPromise . resolve ( cb ( ) ) . then ( ( ) => value ) , reason => MyPromise . resolve ( cb ( ) ) . then ( ( ) => { throw reason ; } ) ) ; } static resolve ( value ) { if ( value instanceof MyPromise ) return value ; return new MyPromise ( resolve => resolve ( value ) ) ; } static reject ( value ) { return new MyPromise ( ( resolve , reject ) => reject ( value ) ) ; } static all ( list ) { return new MyPromise ( ( resolve , reject ) => { let values = [ ] ; let count = 0 ; for ( let [ i , p ] of list . entries ( ) ) { this . resolve ( p ) . then ( res => { values [ i ] = res ; count ++ ; if ( count === list . length ) resolve ( values ) ; } , err => { reject ( err ) ; } ) ; } } ) ; } static race ( list ) { return new MyPromise ( ( resolve , reject ) => { for ( let p of list ) { this . resolve ( p ) . then ( res => { resolve ( res ) ; } , err => { reject ( err ) ; } ) ; } } ) ; } }