zoukankan      html  css  js  c++  java
  • 一个简单的例子搞懂ES6之Promise

    ES5中实现异步的常见方式不外乎以下几种:

    1. 回调函数

    2. 事件驱动

    2. 自定义事件(根本上原理同事件驱动相同)

    而ES6中的Promise的出现就使得异步变得非常简单。promise中的异步是这样的:

    * 每当我需要执行一次异步操作的时候,我都需要new一个promise对象

    * 每一个异步操作的Promise对象都需要设定一个成功执行的条件和成功的回调、一个失败的条件和失败的回调

    * Promise对象可通过执行then()方法获得成功的回调信息

    * Promise对象可通过执行catch()方法捕获失败的回调信息(当不执行catch方法时,若异步操作失败会报错)

    一次常规异步操作的流程大致是这样的:

        new Promise((resolve, reject)=>{
            if(...){             // 设定异步操作成功的条件
                resolve()        // 设定异步操作成功 并返回 成功的回调信息
            } 
            else{               // 设定异步操作失败的条件
                reject()        // 设定异步操作失败 并返回 失败的回调
            }
        })
        .then((res)=>{         //执行异步操作,并且执行成功
            .....             // 异步操作成功后的后续操作
            ...
            ..               
        })
        .catch((err)=>{    // 执行一步操作,异步操作失败
            .....          // 操作失败的后续操作
            ...
            ..
        })

    下面首先通过一个简单的例子来基本套用一下异步操作的流程

    实际项目中经常会有这样的需求,很多功能都是需要在登录后才能去实现的,比如说我想要查看用户的个人信息,那么这个用户就必须先要登录,那么分解步骤后

    第一步: 执行登录并且登录成功

    第二步: 登录成功,开始获取用户信息

    第三步: 获取用户信息成功,返回用户信息或成功的回调信息。

    以上三步操作,需要两次异步操作,就需要两个异步的Promise对象

    首先是准备工作:

        // 两个状态用以分别判断两次异步操作是否成功
        let status1 = 1;
        let status2 = 1;
        // 设定登录的异步操作
        let doLogin = (resolve, reject) =>{
            setTimeout(()=>{
                if(status1 ==1){
                    resolve({status:1,msg: `异步执行 login ok`})
                }else{
                    reject({status:0,msg: `异步执行 login failed`});
                }
            },2000)
        }
        // 设定获取用户信息的异步操作
        let getUserInfo = (resolve, reject)=>{
            setTimeout(()=>{
                if(status2==1){
                    resolve({status:1,msg: `异步执行 get user info ok`});
                }else{
                    reject({status:0,msg: `异步执行 get user info failed`});
                }
            },1000)
        }

    紧接着开始执行异步操作:

        new Promise(doLogin)
        .then((res)=>{
            if(res.status==1){
                console.log(res.msg);
                return new Promise(getUserInfo)     // 若下一步要执行异步操作则必须返回一个promise对象用以链式操作
            }else{
                console.log(res.msg);
            }
        })
        .then((res)=>{
            console.log(res.msg)
        })
        .catch((err)=>{
            console.log(err.msg)
        })

    感兴趣的可以通过控制status1、status2两个状态码体验一下不同情况下异步操作的流程与结果。

    上面的例子搞清楚之后差不多也就理解了promise的基本用法。

    你也可以配合同步代码体验效果:

        console.log("同步执行111111111")
        new Promise(doLogin)
        .then((res)=>{
            if(res.status==1){
                console.log(res.msg);
                return new Promise(getUserInfo)
            }else{
                console.log(res.msg);
            }
        })
        .then((res)=>{
            console.log(res.msg)
        })
        .catch((err)=>{
            console.log(err.msg)
        })
        console.log("同步执行2222222")

    而当你需要实现连续的异步操作时,需要在每一步异步操作后都返回一个promise对象,否则执行的还是同步操作。下面的例子可以证明:

        let afterLogin1 = ()=>{
            console.log("登录后续操作1")
        }
        let afterLogin2 = ()=>{
            console.log("登录后续操作2")
        }
    
        new Promise(doLogin)
        .then((res)=>{
            console.log(res.msg)
        })
        .then((res)=>{
            setTimeout(()=>{
                afterLogin1();
            },1000)
        })
        .then((res)=>{
            afterLogin2();
        })

    例子的输出结果为:

    异步执行 login ok

    登录后续操作2

    登录后续操作1

     Promise.all()   多异步操作,所有异步执行需全部成功

     all()  方法需要传入的参数为对象数组,只有当数组中的所有异步对象都能够成功回调后,all() 方法返回的promise对象才能执行成功的回调。

    * 创建Promise对象:

        function creatPro (flag,oSucc,oFail) {
            let pro = new Promise((resolve, reject)=>{
                setTimeout(()=>{
                    if(flag){
                        resolve(oSucc)
                    }else{
                        reject(oFail)
                    }
                },1000)
            })
            return pro
        }

    当所有异步对象都能执行成功回调时,all方法的成功回调返回一个所有对象成功回调数据的集合

        let p1 = creatPro(true,{status:1,msg:"异步成功1"},{status:0,msg:"异步失败1"});
        let p2 = creatPro(true,{status:1,msg:"异步成功2"},{status:0,msg:"异步失败2"});
        let p3 = creatPro(true,{status:1,msg:"异步成功3"},{status:0,msg:"异步失败3"});
    
        Promise.all([p1,p2,p3])
        .then((res)=>{
            console.log(res);
        })
        .catch((err)=>{
            console.log(err);
        })

    * 当出现失败的异步操作时,则返回第一个失败的异步回调信息

        let p1 = creatPro(true,{status:1,msg:"异步成功1"},{status:0,msg:"异步失败1"});
        let p2 = creatPro(false,{status:1,msg:"异步成功2"},{status:0,msg:"异步失败2"});
        let p3 = creatPro(false,{status:1,msg:"异步成功3"},{status:0,msg:"异步失败3"});

    控制台的结果为:{status: 0, msg: "异步失败2"}

    Promise.race()   多异步操作,顾名思义,返回的为第一个执行完成的回调信息,无论是成功还是失败。

    看的是执行的速度,谁快返回谁:

        function creatPro (flag,oSucc,oFail,timeout) {
            let pro = new Promise((resolve, reject)=>{
                setTimeout(()=>{
                    if(flag){
                        resolve(oSucc)
                    }else{
                        reject(oFail)
                    }
                },timeout)
            })
            return pro
        }
    
        let p1 = creatPro(true,{status:1,msg:"异步成功1"},{status:0,msg:"异步失败1"},5000);
        let p2 = creatPro(false,{status:1,msg:"异步成功2"},{status:0,msg:"异步失败2"},1000);
        let p3 = creatPro(true,{status:1,msg:"异步成功3"},{status:0,msg:"异步失败3"},500);
    
        Promise.race([p1,p2,p3])
        .then((res)=>{
            console.log(res);
        })
        .catch((err)=>{
            console.log(err);
        })

    执行结果:{status: 1, msg: "异步成功3"}

  • 相关阅读:
    动态规划算法介绍——概念、意义及应用、例题
    两个大数相减
    删除apache的签名的shell脚本
    C++中智能指针的设计和使用
    eclipse save action不起作用
    [leetcode]51. N-QueensN皇后
    [leetcode]33. Search in Rotated Sorted Array旋转过有序数组里找目标值
    [leetcode]88. Merge Sorted Array归并有序数组
    [leetcode]636. Exclusive Time of Functions函数独占时间
    [leetcode]257. Binary Tree Paths二叉树路径
  • 原文地址:https://www.cnblogs.com/pomelott/p/8999039.html
Copyright © 2011-2022 走看看