关于Promises

2019-03-15  本文已影响0人  钟钟353251

一、名字

        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,报“图片请求超时”的信息。

上一篇下一篇

猜你喜欢

热点阅读