es6之为什么要用Promise (承诺)

为什么要用Promise (承诺)  多层回调代码降维 ,异步编程

来看一下以下代码:ajax的多次请求(形成V型代码结构),产生了回调地狱,

不论是浏览器中最为常见的ajax、事件监听,还是node中文件读取、网络编程、数据库等操作,都离不开异步编程。在异步编程中,许多操作都会放在回调函数(callback)中。同步与异步的混杂、过多的回调嵌套都会使得代码变得难以理解与维护,这也是常受人诟病的地方。————(某博客摘录)

代码降维思想 A执行成功后 把自己的状态交给S1, B监听S1的状态,成功后执行,代码结构就变得清晰
A
  S1  pending => success/error
B
  S2  pending => success/error
C
  S3  pending => success/error
D
  S4  pending => success/error
E 

Promise 就此受到广泛的应用

古人云:“君子一诺千金”,这种“承诺将来会执行”的对象在JavaScript中称为Promise对象。 ————(某大牛博客摘录)

Promise 是一种异步解决方案,最早由社区提出并实现,后来写进了es6规范

模拟ABC执行:

let p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log(`A is finshed`)
        resolve('YES')
    }, 2000)
})

let p2 = p1.then((data) => {
    console.log(data)
    return new Promise((suc, err) => {
        setTimeout(() => {
            err('NO')
            console.log(`B is finshed`)
        }, 2000)
    })
}, (err) => {
    console.log(err)
})

let p3 = p2.then((data) => {
    console.log(data)
}, (err) => {
    console.log(err)
})

图片请求

function loadUrl(url) {
    let img = new Image()
    return new Promise((resolve, reject) => {
        img.onload = () => resolve(img)
        img.noerror = () => reject(`${url} is not an effective URL`)
        img.src = url
    })
}
//错误的URL 有BUG
loadUrl('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1536508763099&di=cf94cd77fc462f08cc9e47df4f48bef1&imgtype=jpg&src=http%3A%2F%2Fimg3.imgtn.bdimg.com%2Fit%2Fu%3D4010600603%2C2924105424%26fm%3D214%26gp%3D0.jpg').then(img => document.body.appendChild(img), err => console.log(err))

Promise对象有以下两个特点:对象状态不受外界影响 和 一旦状态改变,就不会再变,任何时候都可以得到这个结果

promise状态的不可逆性;

let p = new Promise((resolve, reject)=> {
    reject("我执行了,后面改变不了状态")
    resolve('他先执行他是老大')
})

Promise也有一些缺点:

1.一旦新建,就会立即执行,无法中途取消。

2.如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。

3.当处于pending状态时,无法得知目前进展到哪一个阶段。

(如果某些事件不断地反复发生,一般来说,使用stream模式比部署Promise更好。)不了解stream模式   (摘录)

手动封装promise功能实现(同步版本。未封装异步状态)

class myPromise {
    constructor(fn) {
        if (typeof (fn) !== 'function') {
            throw TypeError(`myPromise resolve ${fn} is not a function`)
        }

        this.status = 'pending'
        this.data = undefined

        let resolve = (value) => {
            if (this.status === 'pending') {
                this.status = 'resolved'
                this.data = value
            }
        }

        let reject = (value) => {
            if (this.status === 'pending') {
                this.status = 'rejected'
                this.data = value

            }
        }

        if (this.status === 'pending') {
            

        }
        fn(resolve, reject)
    }

    then(resolveFn, rejectFn) {
        if (this.status === 'resolved') {
            if (resolveFn !== 'function') {
                return myPromise.resolve(this.data)
        } else {
            let res = resolveFn(this.data)
            if (res instanceof myPromise) {
                return res
            } else {
                return myPromise.resolve(this.data)
            }
            }
        }

        if (this.status === 'rejected') {
            if (rejectFn !== 'function') {
                return myPromise.reject(this.data)
        } else {
            let res = rejectFn(this.data)
            if (res instanceof myPromise) {
                return res
            } else {
                return myPromise.resolve(this.data)
            }
            }
        }
    }
    static resolve(data) {
        return new myPromise((resolve, reject) => {
            resolve(data)
        })
    }
    static reject(data) {
        return new myPromise((resolve, reject) => {
            reject(data)
        })
    }
}

经过偶尔的灵感突发和XXX最终实现了异步,对于处于在pending的封装,需要通过回调函数来实现

当处于pending状态时(异步等待中),我们创建一个新的promise对象。给未来会产生的成功和失败状态添加上回调函数。

class myPromise {
    constructor(fn) {
        if (typeof (fn) !== 'function') {
            throw TypeError(`myPromise resolve ${fn} is not a function`)
        }

        this.status = 'pending'
        this.data = undefined
        this.resolveCB = null
        this.rejectCB = null

        let resolve = (value) => {
            if (this.status === 'pending') {
                this.status = 'resolved'
                this.data = value
                // console.log(this.resolveCB)
                this.resolveCB && this.resolveCB()

            }
        }

        let reject = (value) => {
            if (this.status === 'pending') {
                this.status = 'rejected'
                this.data = value
                this.rejectCB && this.rejectCB()
            }
        }
        fn(resolve, reject)
    }

    then(resolveFn, rejectFn) {
        if (this.status === 'resolved') {
            if (resolveFn !== 'function') {
                return myPromise.resolve(this.data)
            } else {
                let res = resolveFn(this.data)
                if (res instanceof myPromise) {
                    return res
                } else {
                    return myPromise.resolve(this.data)
                }
            }
        }
        if (this.status === 'rejected') {
            if (rejectFn !== 'function') {
                return myPromise.reject(this.data)
            } else {
                let res = rejectFn(this.data)
                if (res instanceof myPromise) {
                    return res
                } else {
                    return myPromise.resolve(this.data)
                }
            }
        }
        if (this.status === 'pending') {
            return new myPromise((resolve, reject) => {
                this.resolveCB = ((resolveFn) => {
                    return () => {
                        let res = resolveFn(this.data)
                        if (res instanceof myPromise) {
                            res.then(resolve, reject)
                        } else {
                            resolve(res)
                        }
                    }
                })(resolveFn)
                
                this.rejectCB = ((rejectFn)=>{
                    return ()=>{
                        let res = rejectFn(this.data)
                        if(res instanceof myPromise){
                            res.then(resolve,reject)
                        }else{
                            reject(res)
                        }
                    }
                })(rejectFn)
            })
        }
    }
    static resolve(data) {
        return new myPromise((resolve, reject) => {
            resolve(data)
        })
    }
    static reject(data) {
        return new myPromise((resolve, reject) => {
            reject(data)
        })
    }
}

当执行结果处于异步的时候(主线程代码执行完才会去操作异步),异步传回一个状态,这时候就需要给当前状态添加回调函数。回调函数的内容是改变pending状态。回调函数会执行新的pormise。这时,新的promose状态就确定了,把新的peomise状态传出。实现异步操作。

未完待续,求大神指点一二!!!

猜你喜欢

转载自blog.csdn.net/qq_35401191/article/details/82556573