美文网首页
Promise基础

Promise基础

作者: 小吉头 | 来源:发表于2020-10-15 16:50 被阅读0次

    什么是promise

    • 抽象表达
      Promise是JS中进行异步编程的新的解决方案(Promise也支持回调),旧的方案是通过纯回调的方式
    • 具体表达
      从语法上:Promise是一个构造函数
      从功能上:promise对象用来封装一个异步操作并可以获取其结果

    promise对象状态改变

    初始时是pending,表示未确定的状态,接下来可能有两种情况:
    1、pending 变为 resolved
    2、pending 变为 rejected
    说明:只有这2种情况,不存在从resolved->pending或者rejected->pending的情况。并且一个promise对象只能改变一次

    • 无论变为成功还是失败,都会有一个结果数据
    • 成功的结果数据一般称为value,失败的结果数据一般称为reason

    promise流程

    Promise基本使用

        <script>
            //1、创建一个新的promise对象
            const p = new Promise((resolve,reject) => { //reslove和reject是函数对象, (resolve,reject) => {} 叫执行器函数
                //2、执行异步任务
                setTimeout(() => {
                    const time = Date.now() //当前时间是偶数代表成功,否则代表失败
                    //3.1 如果成功,调用relosve(value)
                    if (time %2 == 0){
                        resolve('success data')
                    }else{
                        //3.2 如果失败,调用reject(reason)
                        reject('fail data')
                    }
                },1000);
    
            })
            p.then( //指定成功的回调函数(即onResolved,表示当状态变为resolved时执行该回调函数)和失败的回调函数(onRejected,表示当状态变为rejected时执行该回调函数)
                value => { //接收成功的value
                    console.log('成功的回调,数据是:',value)
                },
                reason => { //接收失败的reason
                    console.log('失败的回调,数据是:',reason)
                }
            )
    </script>
    

    执行器函数是同步回调还是异步回调?
    根据之前的规则,加上console.log打印,看下输出:

    <script>
            //1、创建一个新的promise对象
            const p = new Promise((resolve,reject) => { //reslove和reject是函数对象, (resolve,reject) => {} 叫执行器函数
                console.log("执行 executor")
                //2、执行异步任务
                setTimeout(() => {
                    const time = Date.now() //当前时间是偶数代表成功,否则代表失败
                    //3.1 如果成功,调用relosve(value)
                    if (time %2 == 0){
                        resolve('success data')
                    }else{
                        //3.2 如果失败,调用reject(reason)
                        reject('fail data')
                    }
                },1000);
                console.log('executor 执行结束')
    
            })
            console.log('new Promise()之后')
            p.then( //指定成功的回调函数(即onResolved,表示当状态变为resolved时执行该回调函数)和失败的回调函数(onRejected,表示当状态变为rejected时执行该回调函数)
                value => { //接收成功的value
                    console.log('成功的回调,数据是:',value)
                },
                reason => { //接收失败的reason
                    console.log('失败的回调,数据是:',reason)
                }
            )
    </script>
    
    >>>执行 executor
    >>>executor 执行结束
    >>>new Promise()之后
    >>>成功的回调,数据是: success data
    

    执行器函数先输出,因此这里的执行器函数是同步回调
    执行器函数 打印执行 executor->启动异步任务->new Promise()之后 ,至此执行器函数结束,也就是new Promise()函数结束并返回了promise对象。
    总结:当得到promise对象时,异步任务已经启动了,正在执行,还没完成。所以返回promise对象是很迅速的,只要启动异步任务即可,不管它有没有完成。

    Promise的作用

    1、promise指定回调函数的方式更加灵活

    • 纯回调方式
    <script>
            //成功的回调函数
            function successCallback(result){
                console.log("声音文件创建成功:"+result)
            }
            //失败的回调函数
            function failureCallback(error){
                console.log("声音文件创建失败:"+error)
            }
    
            //使用纯回调函数,在启动异步任务之前必须指定成功和失败回调函数
            //createAudioFileAsync是一个耗时操作,第一个参数是创建音频文件的配置信息,successCallback是成功的回调函数,failureCallback是失败的回调喊
            createAudioFileAsync(audioSettings,successCallback,failureCallback)
    </script>
    
    • 使用promise
        <script>
            function createAudioFileAsync(audioSettings){
                const p = new Promise((resolve,reject) => { //执行器函数
                //2、执行异步任务
                startCreateAudioFile(audioSettings)
                //返回promise对象
                return p
            }
    
            //使用promise,createAudioFileAsync(audioSettings)返回promsie对象,异步任务在该promsie对象内部执行(即执行器中执行)
            const promise = createAudioFileAsync(audioSettings);
    
            //异步任务还在执行中,就指定回调函数
            //promise.then(successCallback,failureCallback); #此时异步任务已经启动,还没有结果
            //异步任务已经得到结果了,才指定回调函数
            // setTimeout(() => { #假设异步任务执行需要10秒,这里延时了20秒,此时异步任务已经有结果
            //  promise.then(successCallback,failureCallback);
            // },20000)
        </script>
    

    根据上面总结可知,const promise = createAudioFileAsync(audioSettings);当得到promise对象时,创建音频文件的异步任务已经启动,还没完成

    总结

    纯回调:必须在启动异步任务前指定
    promise:可以在启动异步任务之后指定(此时异步任务还在执行中),也可以过一段时间再指定(假设此时异步任务已经有结果了)

    2、promise解决回调地狱问题

    • 纯回调函数可能出现回调地狱
        <script>
            doSomething1(function(result1){
                doSomething2(result1,function(result2){
                    doSomething3(result2,function(result3){
                        console.log('get final result:',result3)
                    },failureCallback3)
                },failureCallback2)
            },failureCallback1)
        </script>
    

    doSomething1执行成功后进入成功回调函数并传入result1,doSomething2依赖result1作为参数,执行成功后进入成功的回调函数并传入result2,doSomething3依赖result2作为参数,执行成功后进入成功回调函数并传入result3
    代码整体向右发展,不方便阅读,每个函数都要单独做异常处理

    • promise方式
        <script>
            doSomething1()
            .then(function(result1){
                return doSomething2(result1)
            })
            .then(function(result2){
                return doSomething3(result2)
            })
            .then(function(result3){
                console.log('get final result:',result3)
            })
            .catch(failureCallback)
        </script>
    

    doSomething1()、doSomething2(result1)、doSomething3(result2)得到的都是promise对象
    代码整体是纵向,可阅读性好。所有的then()只写了成功的回调,任何的失败回调会通过异常传透到最下面的catch被捕获

    • 更优方案,使用async/await
      promise虽然没有回调函数嵌套,但是还是存在回调函数,从语法层面去掉回调(虽然编译后是有回调的)
        <script>
            async function request(){
                try{
                    const result1 = await doSomething1()
                    const result2 = await doSomething2()
                    const result3 = await doSomething3()
                    console.log('get final result:',result3)
                }catch(error){
                    failureCallback(error)
                }
            }
        </script>
    

    相关文章

      网友评论

          本文标题:Promise基础

          本文链接:https://www.haomeiwen.com/subject/aamnpktx.html