美文网首页
大白话讲解Promise

大白话讲解Promise

作者: 云凡的云凡 | 来源:发表于2020-12-19 19:24 被阅读0次

https://www.cnblogs.com/lvdabao/p/es6-promise-1.html 讲得很好

一、链式操作的用法、resolve() 的用法

    <script>
        console.dir(Promise);
        function fun0() {
            var p = new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log("执行完成任务0");
                    resolve('随便什么数据0')
                }, 1000)
            })
            return p
        }
        function fun1() {
            var p1 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log("执行完成任务1");
                    resolve('随便什么数据1')
                }, 1000)
            })
            return p1
        }
        function fun2() {
            var p2 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log("执行完成任务2");
                    resolve('随便什么数据2')
                }, 1000)
            })
            return p2
        }
        function fun3() {
            var p3 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log("执行完成任务3-");
                    resolve('随便什么数据3')
                }, 1000)
            })
            return p3
        }
        fun0().then((data) => {
            console.log(data);
            return fun1()
        }).then((data) => {
            console.log(data);
            return fun2()
        }).then((data) => {
            console.log(data+`结束`);
            // return fun3()
        })

    </script>

二、reject的用法

<script>
        function getNum() {
            var p = new Promise((resolve, reject) => {
                setTimeout(() => {
                    var num = Math.ceil(Math.random() * 10)     //生成1-10的随机数
                    num <= 5 ? resolve(num) : reject('数字不符合')
                }, 500)
            })
            return p
        }
        getNum().then(
            (data) => {
                console.log('resolved');
                console.log(data);
            },
            //then的第二个参数,用来指定reject的回调
            (reason, data) => {   //调用reject并传递一个参数,作为失败的原因。
                console.log('rejected');
                console.log(reason);
            }
        )

    </script>

有两种结果:
状态置为fullfiled

image.png
或者
状态置为rejected
image.png

三、catch的用法

我们知道Promise对象实例可以共享 Promise 构造函数上的then、catch、finally等方法,catch和then的第二个参数一样,用来指定reject的回调,用法是这样:

        function getNum() {
            var p = new Promise((resolve, reject) => {
                setTimeout(() => {
                    var num = Math.ceil(Math.random() * 10)  ////生成1-10的随机数
                    num <= 5 ? resolve(num) : reject('数字不符合')
                }, 500)
            })
            return p
        }
        getNum().then(
            (data) => {
                console.log('resolved');
                console.log(data);
            }

            // (reason, data) => {
            //     console.log('rejected');
            //     console.log(reason);
            // }
        ).catch(function (reason) {
            console.log('rejected');  //效果和写在then的第二个参数里面一样。
            console.log(reason);
        })

效果和写在then的第二个参数里面一样。不过它还有另外一个作用:在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中。请看下面的代码:

    <script>
        function getNum() {
            var p = new Promise((resolve, reject) => {
                setTimeout(() => {
                    var num = Math.ceil(Math.random() * 10)  ////生成1-10的随机数
                    num <= 5 ? resolve(num) : reject('数字不符合')
                }, 500)
            })
            return p
        }
        getNum().then(
            (data) => {
                console.log('resolved');
                console.log(data);
                console.log(somedata); //此处的somedata未定义
            }

            // (reason, data) => {
            //     console.log('rejected');
            //     console.log(reason);
            // }
        ).catch(function (reason) { //效果和写在then的第二个参数里面一样。
            console.log('rejected');  
            console.log(reason);
        })

    </script>
image.png

也就是说进到catch方法里面去了,而且把错误原因传到了reason参数中。即便是有错误的代码也不会报错了,这与我们的try/catch语句有相同的功能。

四、all的用法

Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。我们仍旧使用上面定义好的fun0(), fun1(), fun2(), fun3()这四个函数,看下面的例子:

  <script>
        console.dir(Promise);
        function fun0() {
            var p = new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log("执行完成任务0");
                    resolve('随便什么数据0')
                }, 1000)
            })
            return p
        }
        function fun1() {
            var p1 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log("执行完成任务1");
                    resolve('随便什么数据1')
                }, 1000)
            })
            return p1
        }
        function fun2() {
            var p2 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log("执行完成任务2");
                    resolve('随便什么数据2')
                }, 1000)
            })
            return p2
        }
        function fun3() {
            var p3 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log("执行完成任务3-");
                    resolve('随便什么数据3')
                }, 1000)
            })
            return p3
        }
        // fun0().then((data) => {
        //     console.log(data);
        //     return fun1()
        // }).then((data) => {
        //     console.log(data);
        //     return fun2()
        // }).then((data) => {
        //     console.log(data + `结束`);
        //     // return fun3()
        // })
        Promise.all([fun0(), fun1(), fun2(), fun3()]).then((results) => {
            console.log(results);
        })
    </script>

用Promise.all来执行,all接收一个数组参数,里面的值最终都算返回Promise对象。这样,三个异步操作的并行执行的,等到它们都执行完后才会进到then里面。那么,三个异步操作返回的数据哪里去了呢?都在then里面呢,all会把所有异步操作的结果放进一个数组中传给then,就是上面的results。所以上面代码的输出结果就是:


image.png

有了all,你就可以并行执行多个异步操作,并且在一个回调中处理所有的返回数据,是不是很酷?有一个场景是很适合用这个的,一些游戏类的素材比较多的应用,打开网页时,预先加载需要用到的各种资源如图片、flash以及各种静态文件。所有的都加载完后,我们再进行页面的初始化。

五、race的用法

all方法的效果实际上是「谁跑的慢,以谁为准执行回调」,那么相对的就有另一个方法「谁跑的快,以谁为准执行回调」,这就是race方法,这个词本来就是赛跑的意思。race的用法与all一样,我们把上面fun0(), fun1(), fun2(), fun3()的延时改一下来看一下:

    <script>
        console.dir(Promise);
        function fun0() {
            var p = new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log("执行完成任务0");
                    resolve('随便什么数据0')
                }, 1000)
            })
            return p
        }
        function fun1() {
            var p1 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log("执行完成任务1");
                    resolve('随便什么数据1')
                }, 2000)
            })
            return p1
        }
        function fun2() {
            var p2 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log("执行完成任务2");
                    resolve('随便什么数据2')
                }, 3000)
            })
            return p2
        }
        function fun3() {
            var p3 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log("执行完成任务3-");
                    resolve('随便什么数据3')
                }, 4000)
            })
            return p3
        }
        // fun0().then((data) => {
        //     console.log(data);
        //     return fun1()
        // }).then((data) => {
        //     console.log(data);
        //     return fun2()
        // }).then((data) => {
        //     console.log(data + `结束`);
        //     // return fun3()
        // })
        Promise.race([fun0(), fun1(), fun2(), fun3()]).then((results) => {
            console.log(results);
        })
image.png

你猜对了吗?不完全,是吧。在then里面的回调开始执行时,fun1(), fun2(), fun3()并没有停止,仍旧再执行。于是再过1秒后,输出了他们结束的标志。

这个race有什么用呢?使用场景还是很多的,比如我们可以用race给某个异步请求设置超时时间,并且在超时后执行相应的操作,代码如下:


    <script>
        //请求某个图片资源
        function requestImg() {
            var p = new Promise(function (resolve, reject) {
                var img = new Image();
                img.onload = function () {
                    resolve(img);
                }
                img.src = 'https://www.baidu.com/';
            });
            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);
            });
    </script>

requestImg函数会异步请求一张图片,我把地址写为"xxxxxx",所以肯定是无法成功请求到的。timeout函数是一个延时5秒的异步操作。我们把这两个返回Promise对象的函数放进race,于是他俩就会赛跑,如果5秒之内图片请求成功了,那么遍进入then方法,执行正常的流程。如果5秒钟图片还未成功返回,那么timeout就跑赢了,则进入catch,报出“图片请求超时”的信息。运行结果如下:


image.png

六、总结

ES6 Promise的内容就这些吗?是的,能用到的基本就这些。
我怎么还见过done、finally、success、fail等,这些是啥?这些并不在Promise标准中,而是我们自己实现的语法糖。

本文中所有异步操作均以setTimeout为例子,之所以不使用ajax是为了避免引起混淆,因为谈起ajax,很多人的第一反应就是jquery的ajax,而jquery又有自己的Promise实现。如果你理解了原理,就知道使用setTimeout和使用ajax是一样的意思。说起jquery,我不得不吐槽一句,jquery的Promise实现太过垃圾,各种语法糖把人都搞蒙了,我认为Promise之所以没有全面普及和jquery有很大的关系。后面我们会细讲jquery。

关于Promise还有一些内容是需要讲的,限于篇幅,本文就只作ES6 Promise的讲解,接下来还会有大白话讲解系列:
Promise/A+规范
jquery中的Promise

敬请期待!

相关文章

  • 大白话讲解Promise(一)

    大白话讲解Promise(一)

  • 大白话讲解Promise

    ES2015正式发布(也就是ES6,ES6是它的乳名),其中Promise被列为正式规范。作为ES6中最重要的特性...

  • 大白话讲解Promise

    ES6 Promise 先拉出来遛遛复杂的概念先不讲,我们先简单粗暴地把Promise用一下,有个直观感受。那么第...

  • 大白话讲解Promise

    ES6 Promise 先拉出来遛遛 复杂的概念先不讲,我们先简单粗暴地把Promise用一下,有个直观感受。那么...

  • 大白话讲解Promise

    https://www.cnblogs.com/lvdabao/p/es6-promise-1.html[http...

  • 大白话讲解Promise(一)

    去年6月份, ES2015正式发布(也就是ES6,ES6是它的乳名),其中Promise被列为正式规范。作为ES6...

  • promise

    大白话讲解Promise(一) 在线流程图与测试 封装一个读取文件的函数(回调的演示) 没有回调时 添加回调 返回...

  • promise讲解

    promise 简介 Promise是ES6加入标准的一种异步编程解决方案,通常用来表示一个异步操作的最终完成 (...

  • Promise讲解

    一、定义 Promise 是异步编程[https://so.csdn.net/so/search?q=%E5%BC...

  • ES6-Promise

    参考链接: 1.阮一峰Promise解读 2.Promise用法讲解 Promise含义 Promise是异步编程...

网友评论

      本文标题:大白话讲解Promise

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