• es6新增-Promise详解(异步编程的解决方案1)


    目录

    一. Promise诞生背景

    1.1作用

    1.2场景

    1.3回调地狱示例

    二. Promise实例的状态 (!important)

    2.1.每个Promise实例有三种状态,分别是

    2.2.一旦状态改变(确定),就不会再变了,Promise对象的状态改变,只有两种可能:

    三. Promise的使用

    1.Promise的基本使用

    2.resolve和reject参数的作用

    resolve的作用:

    reject的作用:

    3.promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数

    4.Promise解决回调地狱示例

    5.进一步认识Promise构造函数

    四. Promise的实例方法和静态需求

    1.Promise的实例方法then

    1.1 then的介绍

    1.2 then的返回值

    1.3 then链式结构解决多重嵌套回调地狱问题

    2.Promise的实例方法catch

    3.Promise的实例方法finally

    4.Promise的静态方法

    Promise.resolve()

    Promise.reject()

    Promise.all()

    Promise.race()

    五. Promise的应用(笔试/需求..)

    1.异步加载图片

    2.代码输出顺序(js循环事件)


    一. Promise诞生背景

    1.1作用

    异步编程的一种解决方式,用来解决回调地狱(回调套回调)。

    1.2场景

    所有的异步回调代码(定时器/ajax请求)都可以用Promise

    1.3回调地狱示例

    开始=>2s 买菜=>2s 洗菜=>2s 切菜=>2s 炒菜=>结束

    console.log("开始")

    setTimeout(()=>{console.log("买菜")

            setTimeout(()=>{console.log("洗菜")

                    setTimeout(()=>{console.log("切菜")

                            setTimeout(()=>{console.log("炒菜")

                                    console.log("结束")

                            },2000)

                    },2000)

            },2000)

    },2000)

    二. Promise实例的状态 (!important)

    2.1.每个Promise实例有三种状态,分别是

    pending(进行中),fulfilled(已成功),rejected(已失败)

    创建时候的默认状态是pending,只有异步操作的结果,可以决定当前是哪一种状态,任何操作都无法改变这个状态这也是Promise名字的由来。

    2.2.一旦状态改变(确定),就不会再变了,Promise对象的状态改变,只有两种可能:

    a.从pending变为fulfilled        b.从penging变为rejected

    三. Promise的使用

    1.Promise的基本使用

    Promise是es6的新增的一个构造函数,用来生成Promise实例

    const p = new Promise((resolve,reject)=>{

    //...异步代码(也可以放同步代码)

    //如:ajax请求、定时器、事件、读文件、操作数据库等

    if( 异步操作成功 ){ resolve(value) }

    else{ reject(error) }

    })

    2.resolve和reject参数的作用

    Promise构造函数接受一个函数作为参数,该函数的两个参数分别为resolve和reject.参数的作用:

    resolve的作用:

    将Promise对象的状态从"未完成"变为"已成功",即pending=>resolved

    reject的作用:

    将Promise对象的状态从"未完成"变为"已失败",即pending=>rejected,

    在异步操作失败时调用 , 并将异步操作报出的错误 , 作为参数传递出去

    3.promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数

    p.then((value)=>{   

    //成功  } , (error){     //失败        })

    then方法可以接受两个回调函数作为参数,

    第一个回调函数是Promise对象的状态变为resolved时调用, 成功的回调

    第二个回调函数是Promise对象的状态变为rejected时调用,失败的回调

    这两个函数都是可选的,不一定都要提供,他们接受Promise对象传出的值作为参数

    4.Promise解决回调地狱示例

    (凡是异步的操作,都可以用Promise的方式来改造)

    function cook(stage){

    return new Promise((resolve)=>{

            setTimeout(()=>{  resolve(stage)  },2000)   })        

    }

    console.log("开始");

    cook("买菜").then((value)=>{

    console.log(value)  })

    控制台打印: 开始=>2s 买菜

    5.进一步认识Promise构造函数

    5.1 const p = new Promise( (resolve,reject)=>{

            setTimeout( ()=>{

                    //Promise的状态一旦确定,就不可以再变更了

                    reject("穷,一个人凉快去吧")

             },2*1000 ) 

    } )

    p.then((value)=>{  console.log(value) 

    },error=>{ console.log(error) }  )

    两秒后输出:穷,一个人凉快去吧,执行第二个回调函数

    5.2 const p = new Promise( (resolve,reject)=>{

            setTimeout( ()=>{

                    //Promise的状态一旦确定,就不可以再变更了

                   resolve("富有,迎娶白富美")

                   reject("穷,一个人凉快去吧")

                    //在resolve执行之后,Promise状态变为成功,就不再改变了

             },2*1000 ) 

    } )

    p.then((value)=>{  console.log(value) 

    },error=>{ console.log(error) }  )

    两秒后输出:富有,迎娶白富美,执行第一个回调

    5.3  function cook(stage){

    return new Promise((resolve)=>{

            setTimeout(()=>{  reject("钱不够,没买到") },2000)   })        

    }

    console.log("开始");

    // .then 表示成功的回调,添加error表示失败的回调

    cook("买菜").then((value)=>{

    console.log(value)  },(error)=>{ console.log(error) }  )

    控制台打印:开始=>2s 钱不够,没买到

    注:成功回调走.then,失败回调走error

    四. Promise的实例方法和静态需求

    1.Promise的实例方法then

    1.1 then的介绍

    Promise实例具有then方法,也就是说,then方法是定义在原型对象Promise、prototype上的。

    作用:为Promise实例添加改变状态时的回调函数

    参数:then方法的第一个参数是resolved状态(成功态)的回调函数,第二个参数是rejected状态(失败态)的回调函数,他们都是可选的。

    1.2 then的返回值

    then方法返回的是一个新的Promise实例

    (注意:不是原来那个Promise实例,状态又从pending开始)

    因此,可以采用链式写法,即then方法后面再调用另一个then方法。

    const p = new Promise(  ( resolve,reject )=>{ 

    setTimeout( ()=>{

            resolve("成功")

            //reject("失败")

    },1000 )}  )

    p

            .then((v1)=>{ 

                    console.log(v1)

                    //1.返回一个普通值(表明新的Promise实例状态是成功的)

                    return 1

                    //2.返回一个新的Promise实例,状态由resolve或reject函数决定

                    return new Promise((resolve,reject)=>{

                    setTimeout( ()=>{

                            resolve("success")

                            //reject("fail")

                    } )

                    },1000)

                     },error=>{

                            console.log(error)

                            return 2

                    }  )

            .then((v2)=>{  console.log("v2")  },error=>{ console.log(error) }  )

    不同情况输出:

    const p = new Promise(  ( resolve,reject )=>{ 

    setTimeout( ()=>{

            resolve("成功")

    },1000 )}  )

    p

            .then((v1)=>{ 

                    console.log(v1)

                    return 1

                     },error=>{

                            console.log(error)

                            return 2

                    }  )

            .then((v2)=>{  console.log("v2")  },error=>{ console.log(error) }  )

    输出:成功 1

    const p = new Promise(  ( resolve,reject )=>{ 

    setTimeout( ()=>{

            resolve("成功")

    },1000 )}  )

    p

            .then((v1)=>{ 

                    return new Promise((resolve,reject)=>{

                    setTimeout( ()=>{

                            resolve("success")

                    } )

                    },1000)

                     },error=>{

                           console.log(error)

                            return 2

                    }  )

            .then((v2)=>{  console.log("v2")  },error=>{ console.log(error) }  )

    输出:成功 success

    const p = new Promise(  ( resolve,reject )=>{ 

    setTimeout( ()=>{

            reject("失败")

    },1000 )}  )

    p

            .then((v1)=>{ 

                    return new Promise((resolve,reject)=>{

                    setTimeout( ()=>{

                            resolve("success")

                    } )

                    },1000)

                     },error=>{

                            console.log(error)

                            return 2

                    }  )

            .then((v2)=>{  console.log("v2")  },error=>{ console.log(error) }  )

    输出:失败 success

    const p = new Promise(  ( resolve,reject )=>{ 

    setTimeout( ()=>{

            reject("失败")

    },1000 )}  )

    p

            .then((v1)=>{ 

                    return new Promise((resolve,reject)=>{

                    setTimeout( ()=>{

                            reject("fail")

                    } )

                    },1000)

                     },error=>{

                            console.log(error)

                            return 2

                    }  )

            .then((v2)=>{  console.log("v2")  },error=>{ console.log(error) }  )

    输出:失败 fail

    注:下一个.then走成功还是失败,取决于前一个.then的回调中返回的是resolve还是reject

    1.3 then链式结构解决多重嵌套回调地狱问题

    function cook(stage){

    return new Promise((resolve)=>{

            setTimeout(()=>{  resolve(stage)  },2000)   })        

    }

    console.log("开始");

    cook("买菜").then(v1=>{

            console.log(v1) 

            return cook("洗菜")

    })

    .then(v2=>{

            console.log(v2)

            return cook("切菜")

    })

    .then(v2=>{

            console.log(v3)

            return cook("炒菜")

    })

    .then(v4=>{

            console.log(v4)

            console.log("结束")

    })

    控制台打印: 开始=>2s 买菜=>2s 洗菜=>2s 切菜=>2s 炒菜=>结束

    2.Promise的实例方法catch

    Promise.prototype.catch()方法是

    .then(null,rejectCallback) .then(undefined,rejectCallback)的别名

    用于指定Promise发生错误/失败时的回调函数

    const p = new Promise((resolve,reject)=>{

            setTimeout(()=>{

                    reject("出错啦")

            },1000)

    })

    //如果 只是处理失败有两种方法

    //1.then 的第二个回调

    p

            .then(null,error=>{

                    console.log(error)

            })

    //2.等价于catch方法

    p

            .catch(error=>{

                    console.log(error)

            })

    输出:出错啦

    3.Promise的实例方法finally

    Promise.prototype.finally()

    finally()方法的作用:不管Promise实例最后状态是成功还是失败,都会执行的操作,该方法是es2018引入标准的

    类似于代码块:

    try{

    }catch(e){

    }finally{

    }

    示例

    const p = new Promise((resolve,reject)=>{

    setTimeout(()=>{

            resolve("成功");

            //reject("失败")

    },1000)

    })

    p

    .then(value=>{

            console.log(value)

    })

    //catch来捕获回调的失败状态,等同于.then的error

    .catch(error=>{

            console.log(error)

    })

    .finally(()=>{

            console.log("finally无论状态成功还是失败,都会执行")

    })

    输出:成功 finally无论状态成功还是失败,都会执行

    const p = new Promise((resolve,reject)=>{

    setTimeout(()=>{

            reject("失败")

    },1000)

    })

    p

    .then(value=>{

            console.log(value)

    })

    //catch来捕获回调的失败状态,等同于.then的error

    .catch(error=>{

            console.log(error)

    })

    .finally(()=>{

            console.log("finally无论状态成功还是失败,都会执行")

    })

    输出:失败 finally无论状态成功还是失败,都会执行

    4.Promise的静态方法

    Promise.resolve()

    将现有的对象转换为 一个成功态的Promise实例

    Promise.resolve()用法

    Promise.resolve(“成功状态”).then(value=>{console.log(value)})

    等价于

    new Promise(resolve=>resolve("成功状态"))

    Promise.reject()

    将现有对象转换为 一个失败态的Promise实例

    Promise.reject()用法

    Promise.reject("失败状态").catch(error=>{console.log(error)})

    等价于

    new Promise((resolve,reject)=>reject("失败状态"))

    Promise.all()

    const p = Promise.all( [p1,p2,p3...] );

    将多个Promise实例包装成一个新的Promise实例

    p1,p2,p3都是Promise实例,

    如果不是,内部会先调用Promise.resolve()方法,将每个Promise实例包装成成功态的Promise实例,再进一步处理

    内部实例全部为成功态时,才算做整个为成功态,当其中有任一为失败态时,则整体为失败态

    Promise.race()

    将多个Promise实例包装成一个新的Promise实例

    用法与Promise.all()相类似,但是执行不同,

    Promise.race()是成功态还是失败态主要取决于内部p1,p2...哪一个先发生改变,

    Promise.race()跟随内部状态最先变化的实例变化

    延迟打印

    function delayPrint(data){

            return new Promise((resolve,reject)=>{

                    setTimeout(()=>{

                            resolve("data")

                            //reject("错误态")

                    },1000)

            })

    }

    const p1 = delayPrint("I")

    const p2 = delayPrint("like")

    const p3 = delayPrint("money")

    Promise.all([p1,p2,p3]).then(allData=>{

            console.log(allData)   //输出数组 ["I","like","money"]

    })

    Promise.all(["I","like","money"]).then(allData=>{

             console.log(allData)   //输出数组 ["I","like","money"]

    })

    function delayPrint(data){

            return new Promise((resolve,reject)=>{

                    setTimeout(()=>{

                           resolve("data")

                    },1000)

            })

    }

    const p1 = delayPrint("I")

    const p2 = delayPrint("like")

    const p3 = delayPrint("money")

    Promise.race([p1,p2,p3]).then(data=>{

             console.log(data)    //输出 :1,因为1先变化

    },error=>{

            console.log(error)

    })

    function delayPrint(data){

            return new Promise((resolve,reject)=>{

                    setTimeout(()=>{

                            reject("错误态")

                    },1000)

            })

    }

    const p1 = delayPrint("I")

    const p2 = delayPrint("like")

    const p3 = delayPrint("money")

    Promise.all([p1,p2,p3]).catch(error=>{

            console.log(error)   //输出 :错误态

    })

    Promise.race([p1,p2,p3]).then(data=>{

             console.log(data)   

    },error=>{

            console.log(error) //输出 :错误态

    })

    function delayPrint(data){

            return new Promise((resolve,reject)=>{

                    setTimeout(()=>{

                            resolve("data")

                    },1000)

            })

    }

    const p1 = delayPrint("I")

    const p2 = delayPrint("like")

    const p3 = delayPrint("money")

    Promise.race([p1,p2,p3]).then(data=>{

             console.log(data)    //输出 :I,因为p1先变化

    },error=>{

            console.log(error) 

    })

    五. Promise的应用(笔试/需求..)

    1.异步加载图片

    function loadmage(imgUrl){

            return new Promise((resolve,reject)=>{

                    const image = new Image()

                    image.onload = resolve //加载成功执行resolve

                    image.onerror = reject //加载失败执行reject

                    img.src = imgUrl;

            })

    }

    loadImage("xxx.png")

            .then(()=>{})

            .catch(()=>{})

    2.代码输出顺序(js循环事件)

    setTimeout(function(){

            console.log(1)

    },0)  //宏任务

    Promise.resolve().then(()=>{

            console.log(2)

    })  //微任务

    new Promise((resolve)=>{

            resolve(5) //微任务

            console.log(3)

    }) //同步任务

            .then(n=>{

                    console.log(n)

            }) //微任务

    console.log(4)

    输出顺序:3 4 2 5 1

    同步=>微任务=>宏任务

  • 相关阅读:
    【Typescript综合】模块化开发
    vivo数据中心网络链路质量监测的探索实践
    Docker - 安装
    软件测试培训俩月上岗,很慌
    苹果电脑误删除的文件怎么恢复?
    C#的数据集:DataSet对象
    56、MQ(异步通讯的的缺点/优点)
    SWT/ANR问题--如何捕获性能的trace
    论文速览【RL - Exploration】—— 【Go-Explore】First return, then explore
    轻量封装WebGPU渲染系统示例<4>-CubeMap/天空盒(源码)
  • 原文地址:https://blog.csdn.net/m0_65912225/article/details/126102987