面试准备-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链

原文地址:https://www.cnblogs.com/loveliang/p/13932534.html