JavaScript 状态模式

178 阅读1分钟

允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。

老实说不是很好理解的样子,promise就是一种状态模式把。
promise 有三种状态 pending 、fulfilled、rejected。
它会根据不同的状态,有不同的行为。

class Status {
    constructor(status) {
        this.status = status
    }
    
    handle(context) {
        context.setStatus(this)
    }
}

class Context {
    constructor(status) {
        this.status = status
    }
    
    getStatus() {
        return this.status
    }
    
    setStatus(status) {
        this.status = status
        console.log('setStatus', status)
    }
}

class MyPromise {
    constructor(fn) {
        
        this.context = new Context('pending')
        this._resolveStatus = new Status('fulfilled')
        this._rejectStatus = new Status('rejected')
        
        this.thenList = []
        this.catchList = []
    
        fn(this._resolve(), this._reject())
    }
    
    then(fn) {
        this.thenList.push(fn)
    }
    
    catch(fn) {
        this.catchList.push(fn)
    }
    
    _resolve() {
        
        const _this = this
    
        return (res) => {
             setTimeout(() => {
                _this._resolveStatus.handle(_this.context)
                _this.thenList.forEach(fn => fn(res))
                console.log('resolve:', _this.context.getStatus())
            })
        }
    }
    
    _reject() {
    
        const _this = this
        
        return (err) => {
            setTimeout(() => {
                _this._rejectStatus.handle(_this.context)
                _this.catchList.forEach(fn => fn(err))
                console.log('reject:', _this.context.getStatus())
            })
        }
    }
}

const myPromise = new MyPromise((resolve, reject) => {
    
    let flag = true
    if(flag) resolve()
    else reject()
})

const myPromise2 = new MyPromise((resolve, reject) => {
    
    let flag = false
    if(flag) resolve()
    else reject()
})

myPromise
    .then(() => { console.log('then1')})
myPromise
    .then(() => { console.log('then2')})
myPromise2
    .catch(() => { console.log('catch1')})