欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-26 17:49:58
  es6之为什么要用promise (承诺) 2018年09月25日 14:03:03 很小白的小白 数:2 个人分类: es6 为什么要用promise (承诺)? 多层回调代码降维...

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

    2018年09月25日 14:03:03 很小白的小白 数:2 个人分类: es6 为什么要用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状态传出。实现异步操作。

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