zoukankan      html  css  js  c++  java
  • 面试准备-promise基础知识的钻研。

    Promise是什么?

    promise是js处理异步编程的解决方案。

    具体表达:

    从语法上来说,promise是一个构造函数

    从功能上来说,promise对象用来封装一个异步操作并可以获取其结果。

    Promise的状态改变。

    1.pending 变为 resolved。

    2.pedning 变为 rejected。

    说明:promise对象只能改变一次,无论成功还是失败,都会有一个结果数据。

      成功的结果数据一般称为value,失败的结果数据一般称为reason(原因)
    

    Promise的基本流程

    Promise的基本使用

      // 1.创建一个peomise对象
        const p = new Promise((resolve, reject) => {
            // 2.执行异步操作
            setTimeout(() => {
                const time = Date.now()
                // 3.1 如果成功了,调用resolve(value)
                if (time % 2 == 0) {
                    resolve('success'+ time)
                } else {
                    // 3.2 如果失败了,调用reject(reason) 
                    reject('error' + time)
                }
            }, 1000)
        })
    
        p.then(
            value => { //接收得到成功的value数据
                console.log('success11',value)
            },
            reason => { //接收得到失败的reason数据
                console.log('error11',reason)
            }
        )
    

    为什么用Promise?

    1.指定回调函数的方式更加灵活。

    2.支持链式调用,可以解决回调地狱的问题。

    什么是回调地狱:回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调函数的执行条件。

    回调地狱的特点:不便于阅读 / 不便于异常处理。

    解决方案:async + await

    如何使用Promise?

    Promise.resolve() Promise.reject()的使用

     const p1 = new Promise((resolve,reject)=>{
            resolve(1)
        })
        const p2 = Promise.resolve(2)
        const p3 = Promise.reject(3)
        p1.then(value=>{
            console.log(value)
        })
        p2.then(value=>{
            console.log(value)
        })
        p3.catch(reason=>{
            console.log(reason)
        })
        //打印结果 1 2 3 
    

    Promise.all() Promise.race()的使用

    Promise.all() 接收参数是一个数组,数组内是promise对象,必须都成功才会返回成功

    Promise.race() 传的也是一个数组promise对象,判断第一个是否成功

    第一个promise对象成功返回成功,第一个失败返回失败

    并不是谁先前面就是谁,得先看哪个promise先执行完毕

    完整练习代码展示

    const p1 = new Promise((resolve,reject)=>{
            resolve(1)
        })
        const p2 = Promise.resolve(2)
        const p3 = Promise.reject(3)
        p1.then(value=>{
            console.log(value)
        })
        p2.then(value=>{
            console.log(value)
        })
        p3.catch(reason=>{
            console.log(reason)
        })
        //打印结果 1 2 3 
    
            // Promise.all 接收参数是一个数组,数组内是promise对象
            // 必须都成功才会返回成功
        const pAll = Promise.all([p1,p2,p3])
        const pAll1 = Promise.all([p1,p2])
        pAll.then(
            values=>{
                console.log('all onResolved()',values)
            },
            reason=>{
                console.log('all onRejected()',reason) 
                // 打印结果 all onRejected() 3
            }
        )
        pAll1.then(
            values=>{
                console.log('all onResolved()',values)
                 // 打印结果是一个数组  [1,2]
            },
            reason=>{
                console.log('all onRejected()',reason) 
               
            }
        )
        // Promise.race()传的也是一个数组promise对象,判断第一个是否成功
        // 第一个promise对象成功返回成功,第一个失败返回失败
        // 并不是谁先前面就是谁,得先看哪个promise先执行完毕
        const pRace = Promise.race([p1,p2,p3])
        pRace.then(
            values=>{
                console.log('race onResolved()',values)
                // 打印结果 race onResolved() 1
            },
            reason=>{
                console.log('race onRejected()',reason) 
                
            }
        )
    
    

    promise几个常见问题解析。

    1.如何改变promise的状态。

    • 1.resolve(value):如果当前是pendding就会变成resolved

    • 2.reject(reason):如果当前是pendding就会变成rejected

    • 3.抛出异常:如果当前是pendding就会变成rejected

    **代码解析 **

      const p = new Promise((resolve,reject)=>{
            // resolve(1)
            // reject(2)
            throw new Error('error');//抛出异常,promise状态变为reject失败状态,reason为抛出的error。
            // throw 3  //3 "reason"
        })
        p.then(
            value=>{
    
            },
            reason=>{
                console.log(reason,'reason')
            }
        )
    
    

    2. 一个promise指定多个成功/失败的回调函数都会被调用吗?

    当promise改变未对应状态的时候都会调用

    代码解析

    两个then报错的地方都会打印出来

     const p = new Promise((resolve, reject) => {
                // resolve(1)
                // reject(2)
                // throw new Error('error');//抛出异常,promise状态变为reject失败状态,reason为抛出的error。
                throw 3 //3 "reason"
            })
            p.then(
                value => {
    
                },
                reason => {
                    console.log(reason, 'reason')
                }
            )
            p.then(
                value => {
    
                },
                reason => {
                    console.log(reason, 'reason2')
                }
            )
    
    
    

    ** 3.改变promise状态和指定回调函数,谁先谁后?**

    •  1.都有可能,正常情况下先指定回调函数再改变状态,但也可以先改变状态再执行回调。
      
    •  2.如何先改状态再执行回调?
      
        *   1.在执行器中直接调用resolve()/reject()
      
        *   2.延迟更长事件才调用then()
      
    •  3.什么时候才能得到数据?
      
    •         1.如果先指定的回调:那么当状态发生改变时,回调函数就会调用,得到数据
      
    •         2.如果先改变的状态:那当指定回调时,回调函数就会调用,得到数据
      

    常规: 先指定回调函数 后改变promise状态

    
        // 常规: 先指定回调函数 后改变promise状态
        new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(1) //后改变状态(同时指定数据),异步执行回调函数
            }, 1000)
        }).then( // 先指定回调函数,保存当前指定的回调函数
            value => {},
            reason => {}
        )
    
    

    先改变promise状态 后指定回调函数

     // 先改变promise状态 后指定回调函数
        new Promise((resolve, reject) => {
            resolve(1) //先改变状态(同时指定数据)
        }).then( // 后指定回调函数,异步执行回调函数
            value => {console.log(value, 'value')},
            reason => {console.log(reason, 'reason')}
        )
    

    4. promise.then()返回的新promise的结果状态由什么决定?

    **简单描述:由then()指定的回调函数执行的结果决定 **

    来看一下下面的代码输出的是什么?想一想为什么?

     new Promise((resolve, reject) => {
                resolve(1) 
        }).then( 
            value => {console.log(value, 'resolve1')},
            reason => {console.log(reason, 'reject1')}
        ).then( 
            value => {console.log(value, 'resolve2')},
            reason => {console.log(reason, 'reject2')}
        )
    

    答案输出的是

    1 "resolve1"

    undefined "resolve2"

    再来看一下 下面的代码输出什么??

      new Promise((resolve, reject) => {
                // resolve(1) 
                reject(1)
        }).then( 
            value => {console.log(value, 'resolve1')},
            reason => {console.log(reason, 'reject1')}
        ).then( 
            value => {console.log(value, 'resolve2')},
            reason => {console.log(reason, 'reject2')}
        )
    
    

    答案是:

    1 "reject1"

    undefined "resolve2"

    再来看一下 下面的代码输出什么??

     new Promise((resolve, reject) => {
                resolve(1) 
        }).then( 
            value => {
                console.log(value, 'resolve1')
                return 3
            },
            reason => {console.log(reason, 'reject1')}
        ).then( 
            value => {console.log(value, 'resolve2')},
            reason => {console.log(reason, 'reject2')}
        )
    

    答案是:

    ** 1 "resolve1"**

    ** 3 "resolve2"**

    看出来是什么原因了嘛?想一想,再看下面的代码

     new Promise((resolve, reject) => {
                resolve(1) 
        }).then( 
            value => {
                console.log(value, 'resolve1')
                // return 3
                // return Promise.resolve(4);
                // return Promise.reject(5);
                throw 6
            },
            reason => {console.log(reason, 'reject1')}
        ).then( 
            value => {console.log(value, 'resolve2')},
            reason => {console.log(reason, 'reject2')}
        )
    

    可以运行一下代码,改变value中的注释,看看输出的结果。。

    详细解释:

    1.如果抛出异常,新promise变为rejected reason为抛出的异常

    2.如果返回的是非promise的任意值,新promise变为resolved,value为返回的值。

    3.如果返回的是另一个promise,此promise的结果就会成为新promise的结果。

    5. promise如何串联多个操作任务?

     1.  promise的then()返回一个新的promise对象,可以通过then()的链式调用。
    
     2.  通过then的链式调用串多个同步/异步任务
    

    搞个练习,下面代码的输出顺序是什么?

    图片看着方便一些,代码在下面,可以复制运行看一下结果跟自己想的是否一样

    new Promise((resolve, reject) => {
            setTimeout(() => {
                console.log('执行异步任务1')
                resolve(1)
            }, 1000)
        }).then(
            value => {
                console.log(value, '任务1的结果')
                console.log('执行同步任务2')
                // 同步操作,只需要return 一个结果就好
                return 2
            },
        ).then(
            value => {
                console.log(value, '任务2的结果')
                // 异步操作,需要return 一个新的promise对象,用promise的结果作为返回值
                return new Promise((resolve, reject) => {
                    setTimeout(() => {
                        console.log('执行异步任务3')
                        resolve(3)
                    }, 1000)
                })
            },
        ).then(
            value=>{
                console.log(value, '任务3的结果')
            }
        )
    

    答案:

    执行异步任务1

    1 "任务1的结果"

    执行同步任务2

    2 "任务2的结果"

    3 执行异步任务3

    3 "任务3的结果"

    6. promise异常穿透?

    当使用promise中的then链式调用时,可以在最后指定失败的回调。

    前面任何操作出了异常,都会传到最后失败的回调中处理。

    下图输出什么?

    答案是
    ** resolve1 1**
    ** resolve2 2**
    ** resolve3 3**

    改变一行代码,看下图输出什么

    答案是

    ** rejected 1**

    为什么呢?是一步一步的向下传递

    看下图

    6. 中断promise链?

    当使用promise中的then链式调用时,在中间中断,不再调用后面的回调函数。

    办法:在回调函数中返回一个pendding状态的promise对象。

    下图代码输出什么?

    答案是:

    rejected 1

    resolve4 undefined

    现在我想让最后一个then里面的promise不执行,该怎么操作呢?

    看下图//这就是终端promise链

  • 相关阅读:
    4星|万维刚《你有你的计划,世界另有计划》:前物理学家的读书笔记,主要是社会科学领域的书
    3星|《耕作革命》:免耕、保留作物残茬、不同作物轮作的保护性农业,环保且高产
    2.5星|《逆商》:1997年出版的鸡汤,强调积极乐观面对逆境
    3星|《产品游戏化》:游戏类软件产品的宏观开发流程
    2星|曾仕强《人性管理》:故事会水平,像是没有学术背景的讲师
    3.5星|《是谁出的题这么难,到处都是正确答案》:​麦肯锡的经历,文艺妈妈的笔,温馨的父母与丈夫
    基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系。 根据验证过程,远程证书无效------解决方法
    XmlDocument.Load(url) 本地和http远程
    Windows服务启动进程----Cjwdev.WindowsApi.dll
    winform无需安装pdf阅读器打开pdf文件
  • 原文地址:https://www.cnblogs.com/loveliang/p/13932534.html
Copyright © 2011-2022 走看看