美文网首页
关于Promises

关于Promises

作者: 钟钟353251 | 来源:发表于2019-03-15 10:20 被阅读0次

    一、名字

            promise(首字母小写):一个对象,Promise的实例对象

            Promise(首字母大写,单数):Prmoise构造函数

            Promises(首字母大写,复数):指代Promise规范

    二、Promises/A规范和ES6 Prmoises规范

            Prmoises规范有几次升级,目前来说,Promises/A是最新的民间规范。ES6 Prmoises是最新的官方规范。

    三、Promises的意义

            1、解决回调金字塔的问题(回调圣诞树,回调地狱)

            2、可以同时管理成功回调和失败回调

    四、所谓“承诺”

            Promises这个单词翻译为“承诺”。程序的世界里,理解为:我承诺给你完成这些代码的执行。new有一个Prmoise实例,就是js引擎给你一个承诺。

            执行承诺,就会有成功或者失败,只是概率问题。

            在程序世界里,一个承诺也只会有三种状态:“未解决(pendding)”、“成功的(resolve)”、“失败的(reject)”。

    五、Promise构造函数的能力

            本质:prmoises写法的本质就是把 异步写法撸成同步写法。

            怎么做到的呢?

            就是安排一下代码执行的先后顺序:Promise构造函数有特殊的功能,传入Prmoise构造函数的函数参数会优先第一执行,也就是说,只要new一个Prmoise,那么Promise构造函数的函数参数是最高优先级执行的,一直到new一个Promise对象实例后面的then()代码才会执行。链条行的每一个then()都会等到前面promise有了结果才会执行。

            Promise是一个构造函数,用来生成prmoise实例。

            Promise构造函数接受一个函数作为参数,这个函数的两个参数分别是:resolve和reject。他们是两个函数,有js引擎提供(自带的。

            resolve函数的作用:将promise对象的状态从“未完成”变成“成功”。在异步操作成功时调用,并将异步的结果作为参数传递出去。

            reject函数的通:将promise对象的状态从“未完成”变成“失败”。在异步操作失败的时候调用,并将错误作为参数传递出去。

            promise对象生成以后,可以用then()方法分别制定resolve状态和reject状态的回到函数

    六、撸代码

            传统的回调地狱写法:

                    firstAsync(function(data){

                        //拿到data的数据 处理业务逻辑 do something

                        secondAsync(function(data2){

                             //拿到data2的数据 处理业务逻辑 do something

                            thirdAsync(function(data3){

                                    //拿到data3的数据 处理业务逻辑 do something

                            })

                        })

                    })

           哈哈哈,像不像一个金字塔。可读性和维护性都比较差

            引入Promise的写法:

            firstAsync().then(function(data){

                    //拿到data的数据 处理业务逻辑 do something

                    return secondAsync() //继续处理第二个异步

            }).then(function(data2){

                //拿到data2的数据 处理业务逻辑 do something

                return thirdAsync() //继续处理第二个异步

            }).then(function(data3){

                    //拿到data3的数据 处理业务逻辑 do something

            })

            通过then的链式写法,把回调按照顺序串联起来。

            更直接的例子:有做饭、吃饭、洗碗筷这三个异步的操作,他们是层层依赖,下一步的操作依赖上一步操作的结果

            =》

            (1)下面通过样例作为演示,我们定义做饭、吃饭、洗碗(cook、eat、wash)这三个方法,它们是层层依赖的关系,下一步的的操作需要使用上一部操作的结果。(这里使用 setTimeout 模拟异步操作)

                    //做饭    

    function cook(){

    console.log("开始做饭");

    var p = new Promise(function(resolve,reject){

    setTimeout(function(){

    console.log("做饭完毕")

    resolve("老北京炸酱面")

    },1000)

    })

    return p;

    }

    //吃饭

    function eat(data){

    console.log("开始吃饭:"+data)

    var p = new Promise(function(resolve,reject){

    setTimeout(function(){

    console.log("吃饱啦")

    resolve("筷子盘子碗")

    },2000)

    })

    return p

    }

    //洗碗筷

    function wash(data){

    console.log("开始洗碗筷:"+data)

    var p = new Promise(function(resolve,reject){

    setTimeout(function(){

    console.log("洗好啦")

    resolve("干净的碗筷")

    },2000)

    })

    return p

    }

    (2)使用 then 链式调用这三个方法:

    cook()

    .then(function(data){

        returneat(data);

    })

    .then(function(data){

        returnwash(data);

    })

    .then(function(data){

        console.log(data);

    });

    好了,看运行的结果:

    Promises.html:14 开始做饭

    Promises.html:17 做饭完毕

    Promises.html:26 开始吃饭:老北京炸酱面

    Promises.html:29 吃饱啦

    Promises.html:39 开始洗碗筷:筷子盘子碗

    Promises.html:42 洗好啦

    Promises.html:54 干净的碗筷

    七、all

            Promises的all方法,拓展了异步操作的能力,即在所有指定的异步操作都结束后才运行回调。

            直接上代码:

            //切菜

    function cut(){

    console.log("开始切菜:青菜")

    var p = new Promise(function(resolve,reject){

    setTimeout(function(){

    console.log("切菜完毕")

    resolve("切好的青菜")

    },1000)

    })

    return p

    }

    //烧水

    function boil(){

    console.log("开始烧水")

    var p = new Promise(function(resolve,reject){

    setTimeout(function(){

    console.log("烧水完毕")

    resolve("烧好的水")

    },2000)

    })

    return p

    }

    //all then把操作逻辑串起来

    Promise.all([cut(),boil()]).then(function(data){

    console.log("准备工作完毕")

    console.log(data)

    })

    结果:

    开始切菜:青菜

    Promises.html:72 开始烧水

    Promises.html:64 切菜完毕

    Promises.html:76 烧水完毕

    Promises.html:84 准备工作完毕

    Promises.html:85 ["切好的青菜", "烧好的水"]

    八、Promises的race方法:和all类似,是异步能力的拓展,区别是all是所有异步操作都结束才能执行回调, race 的话只要有一个异步操作执行完毕,就立刻执行 then 回调。

    注意:其它没有执行完毕的异步操作仍然会继续执行,而不是停止。

    上面的切菜烧水操作定义好以后:

    Promise.race([cut(),boil()]).then(function(data){

    console.log("至少有一个工作准备好了")

    console.log(data)

    })

    结果注意顺序:

    开始切菜:青菜

    Promises.html:72 开始烧水

    Promises.html:64 切菜完毕

    Promises.html:89 至少有一个工作准备好了

    Promises.html:90 切好的青菜

    Promises.html:76 烧水完毕

    注意,race的应用场景很多,比如同时向后台发起多个ajax的异步请求,并且都有超时时间设置。

    比如:

    //请求某个图片资源

    function requestImg(){

        var p = new Promise(function(resolve, reject){

        var img = new Image();

        img.onload = function(){

          resolve(img);

        }

        img.src = 'xxxxxx';

        });

        return p;

    }

    //延时函数,用于给请求计时

    function timeout(){

        var p = new Promise(function(resolve, reject){

            setTimeout(function(){

                reject('图片请求超时');

            }, 5000);

        });

        return p;

    }

    Promise

    .race([requestImg(), timeout()])

    .then(function(results){

        console.log(results);

    })

    .catch(function(reason){

        console.log(reason);

    });

    上面代码 requestImg 函数异步请求一张图片,timeout 函数是一个延时 5 秒的异步操作。我们将它们一起放在 race 中赛跑。

    如果 5 秒内图片请求成功那么便进入 then 方法,执行正常的流程。

    如果 5 秒钟图片还未成功返回,那么则进入 catch,报“图片请求超时”的信息。

    相关文章

      网友评论

          本文标题:关于Promises

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