再谈promise

promise反复学习总结就会深刻 提高;

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>再谈promise</title>
    </head>
    <body>
        <script type="text/javascript">
            /*
                Promise 出现的原因: 例如ajax【根据第一个网络请求的结果,再去执行第二个网络请求】===> 此时造成回调地狱
                后果:
                    1.代码臃肿
                    2.可读性差
                    3.耦合度过高,可维护性差
                    4.代码复用性差
                    5.容易滋生 bug
                    6.只能在回调里处理异常
                    
                什么是 Promise? 
                     Promise 是异步编程的一种解决方案,比传统的异步解决方案【回调函数】和【事件】更合理、更强大。
                    
                    promise本身是同步的  promise的回调then/catch是异步的
                    async/await也是基于 Promise 实现的
                    async函数内部同步执行,await之间相当于.then。
                    async函数外部的调用异步执行
                传统回调地狱版本:
                请求1(function(请求结果1){
                    请求2(function(请求结果2){
                        请求3(function(请求结果3){
                            请求4(function(请求结果4){
                                请求5(function(请求结果5){
                                    请求6(function(请求结果3){
                                        ...
                                    })
                                })
                            })
                        })
                    })
                })
                
                promise版本:
                new Promise(请求1)
                    .then(请求2(请求结果1))
                    .then(请求3(请求结果2))
                    .then(请求4(请求结果3))
                    .then(请求5(请求结果4))
                    .catch(处理异常(异常信息))
                    
                Promise常用的 API
                    Promise.prototype.then()
                    Promise.prototype.finally(): 不管 Promise 对象最后状态如何,都会执行的操作
                    Promise.all()
                    Promise.allSettled()
                    Promise.race(): Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例
                    Promise.any(): 该方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例返回
                    Promise.resolve()
                    Promise.reject(): 返回一个新的 Promise 实例,实例的状态为rejected
                    Promise.try()
                    Promise.prototype.catch()
                    Promise.try就是模拟try代码块,就像promise.catch模拟的是catch代码块
                Promise有三种状态, pending , resolved , rejected , 只能从等待态转为其他两种状态;
                每次调用then方法,都会返回一个新的promise;
                promise支持链式调用,内部原理采用的是发布订阅模式;
                一定谨记,一个 Promise 对象有三个状态,并且状态一旦改变,便不能再被更改为其他状态!!!
             
            */
            // 首先初始化一个 Promise 对象,可以通过两种方式创建  Promise构造函数【new Promise()】接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数
            // resolve函数的作用是: 将Promise对象的状态从【未完成】变为【成功】(即从 pending => resolved)
            // reject函数的作用是: 将Promise对象的状态从【未完成】变为【失败】(即从 pending => rejected)
            function fn(resolve, reject) {
                console.log('返回promise对象')
                // resolve(1)
            }
            // 方式一
            const promise1 = new Promise(fn)
            console.log(promise1) // Promise {<pending>} 若是fn加上 resolve(1) 则 状态变为 Promise {<fulfilled>: 1}
            // 方式二
            const promise2 = Promise.resolve(fn)
            console.log(promise2) // Promise {<fulfilled>: ƒ}

            /*****************Promise.any() 与 Promise.race() 和 Promise.all() 和 Promise.allSettled()********************/
            // 只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态
            // Promise.any()跟Promise.race()方法很像,只有一点不同,就是不会因为某个 Promise 变成rejected状态而结束
            const q1 = new Promise((resolve, reject) => {
                reject("失败");
            });

            const q2 = new Promise((resolve, reject) => {
                setTimeout(resolve, 300, "后成功");
            });

            const q3 = new Promise((resolve, reject) => {
                setTimeout(resolve, 100, "先成功");
            });

            const q4 = new Promise((resolve, reject) => {
                setTimeout(resolve, 500, "最后成功");
            });

            Promise.any([q1, q2, q3]).then((res) => {
                console.log(res); // 先成功  
            })

            Promise.race([q2, q3, q4]).then((res) => {
                console.log(res); // 先成功  
            })

            Promise.all([q2, q3, q4]).then((res) => {
                console.log(res); // ["后成功", "先成功", "最后成功"]  
            }).catch(e => console.log(e));

            const resolved = Promise.resolve(1);
            const rejected = Promise.reject(-1);
            const allSettledPromise = Promise.allSettled([resolved, rejected]);
            allSettledPromise.then(function(results) {
                console.log(results); // [{status: 'fulfilled', value: 1},{status: 'rejected', reason: -1}]
            });
            // 总结
            // Promise.any()即使第一个返回的 promise 是失败的,Promise.any() 依然使用第一个成功状态的 promise 来返回
            // 这与使用首个(无论 rejected 还是 fullfiled)promise 来返回的 Promise.race() 相反
            // Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝
            // Promise.all(iterable) 方法返回一个 Promise 实例只要有其中一个promise实例是rejected,就会直接走catch方法,并且catch中只会返回第一个变成rejected的promise的错误
            // Promise.race()方法的参数与Promise.all()方法一样,如果不是 Promise 实例,就会先调用Promise.resolve()方法,将参数转为 Promise 实例,再进一步处理
            // Promise.all()无法确定所有请求都结束 Promise.allSettled()就很容易

            /****************************Promise.resolve()**************************************/
            // 需要将现有对象转为 Promise 对象,Promise.resolve()方法就起到这个作用
            const r1 = Promise.resolve('aa')
            console.log(r1, 'r1') // Promise {<fulfilled>: "aa"} "r1"
            // 等价于
            const r2 = new Promise(resolve => resolve('aa'))
            console.log(r2, 'r2') // Promise {<fulfilled>: "aa"} "r2"
            // Promise.resolve()参数的四种情况
            // 1.参数是一个 Promise 实例
            // 如果参数是 Promise 实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例
            // 2.参数是一个thenable对象
            let thenable = {
                then: function(resolve, reject) {
                    resolve(666);
                }
            };
            let promise = Promise.resolve(thenable);
            promise.then(function(res) {
                console.log(res, 'res'); // 666
            });
            // 3.参数不是具有then()方法的对象,或根本就不是对象
            const p = Promise.resolve('Hello world');
            p.then(function(res) {
                console.log(res) // Hello world
            });
            // 4.不带有任何参数
            setTimeout(function() {
                console.log('3');
            }, 0);

            Promise.resolve().then(function() {
                console.log('2');
            });

            console.log('1');
            // 输出的顺序为 1 2 3

            /****************************Promise.reject()**************************************/
            // Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数
            const p1 = Promise.reject('出错了'); // Uncaught (in promise) 出错了
            console.log(p1, 'p1') // Promise {<rejected>: "出错了"} "p1"
            // 等同于
            const p2 = new Promise((resolve, reject) => reject('出错了'))
            p2.then(null, function(r) {
                console.log(r, 'r') // 出错了 r
            });

            // 异步转同步 
            // 1.通过回调函数【回调函数就是将一个函数当作另一个主函数的参数来使用的函数】
            function test2() {
                console.log('执行了test2');
            }

            function test1(cb) { //(主函数)
                console.log('执行了test1');
                setTimeout(function() {
                    cb();
                }, 1000);
            }
            // 执行
            test1(test2);
            // 2 async-await async/await的作用就是使异步操作以同步的方式去执行
            // 一般情况下,async与await配合使用才能使异步操作同步化,await就是等待的意思,等待某一个函数执行完之后,后面的代码才能开始执行
            async function test() {
                return '异步转同步'
            }
            console.log(test()); //Promise { '异步转同步' }
            test().then(res => {
                console.log(res, 'res'); // 异步转同步 'res'
            })

            function fn1() {
                return new Promise(resolve => {
                    setTimeout(function() {
                        msg = 'wait me 3000';
                        resolve(msg)
                    }, 3000);
                });
            }
            async function fn2() {
                var result = await fn1();
                console.log(result);
            }
            fn2();

            // 使用Promise
            function fn3() {
                return new Promise(function(resolve, reject) {
                    setTimeout(function() {
                        msg = 'wait me 3000';
                        resolve(msg);
                    }, 3000);
                })
            }
            fn3().then(data => {
                console.log(data)
            })
        </script>
    </body>
</html>

 自己整理,请勿随意转载!!!!

原文地址:https://www.cnblogs.com/lhl66/p/14450217.html