回调地狱与promise

异步任务同步执行

        需求:假设我们现在有四个定时器,要求在第一个执行完毕后执行第二个,第二个执行完执行第三个...
        这个的常规做法就是嵌套...
setTimeout(function() {
            console.log('定时器1');
            setTimeout(function() {
                console.log('定时器2');
                setTimeout(function() {
                    console.log('定时器3');
                    setTimeout(function() {
                        console.log('定时器4');
                    }, 2000)
                }, 2000)
            }, 2000)
        }, 2000);

这样做是将异步代码变成了同步代码,等待两秒后执行下一个,如果每一层需要执行的代码量非常庞大,就会特别乱 不易阅读与维护,其实上面这个小例子就是回调地狱

promise:

promise 有三个状态:pending:进行中 fulfilled:已成功 rejected:已失败
promise的写法:通过 new Promise内置构造函数创建一个promise对象

  • 构造函数接收一个回调函数作为参数 回调函数需要传入两个参数: resolve 和 reject
    resolve将promise从进行中–已成功
    reject将promise从进行中–已失败
    注意:状态一旦改变 就不能再改回去

  • 捕获成功的状态 通过实例.then方法捕获

  • 捕获失败的状态 通过实例.then方法里面写逗号 另一个回调函数(与写catch是一样的效果)

let promise1 = new Promise(function(resolve, reject) {
            // resolve();
            // reject();
            resolve(x); // x 未定义 所以这是错误的 即使这是将promise变为成功状态 但依旧会走到catch中
            // reject(111);
        });

        promise1.then((value) => {
            console.log('已成功');
        }, (err) => {
            console.log(err); 
            /*
              ReferenceError: x is not defined
              at 06-4promise.html:28
              at new Promise (<anonymous>)
              at 06-4promise.html:25
              如果上面写的是reject(111) 那这里打印111
          */
        })

promise实例.then()方法返回值为一个promise对象 — 链式

let p1 = new Promise(function(resolve, reject) {
            resolve(111);
        })
        console.log(p1); // promise对象
        let p2 = p1.then((val) => {
            console.log(val); // 111
            // return x;
            return 666;
        })
        console.log(p2); // 也是一个新的promise对象 p1.then方法的调用结果就是一个promise对象
        p2.then((val) => {
            console.log(val); // undefined 因为p2没有resolve结果 那就默认为undefined 如果需要给p2抛出一些值 在p2.then中捕获的话 则需要在p1.then的结果中写return
        }, (err) => {
            console.log(err);
        });

解决回调地狱

let p1 = new Promise(function(resolve, reject) {
            resolve(111);
        })
        console.log(p1); // promise对象
        let p2 = p1.then((val) => {
            console.log(val); // 111
            // return x;
            return 666;
        })
        console.log(p2); // 也是一个新的promise对象 p1.then方法的调用结果就是一个promise对象
        p2.then((val) => {
            console.log(val); // undefined 因为p2没有resolve结果 那就默认为undefined 如果需要给p2抛出一些值 在p2.then中捕获的话 则需要在p1.then的结果中写return
        }, (err) => {
            console.log(err);
        });

        /* 
            promise实例.then()方法返回值为一个promise对象 在then中return的值 将作为下一个promise对象捕获的值
            p1.then((v) => {
                console.log(v); // 111
                return 999;
            }).then((v) => {
                console.log(v); // 999
            }) 
        */

        let pro1 = new Promise((resolve, reject) => {
            setTimeout(function() {
                console.log('函数1');
                resolve(); // 2000ms过后让当前pro1的状态变为成功
            }, 2000)
        })
        pro1.then((val) => {
            console.log(val); // udnefined
            return new Promise((resolve, reject) => { // 将下一个promise对象的then中能捕获的值设置为一个新的promise对象的结果 promise一旦创建就开始执行 2000ms后 resolve变为成功的状态 但未抛出值 所以这个新的promise对象的结果为undefined 并且通过return 返回出去 那么下一次then中获取到的val为undefined 
                setTimeout(function() {
                    console.log('函数2');
                    resolve(); 
                }, 2000)
            })
        }).then((val) => {
            console.log(val); // undefined pro1执行完毕时,才会返回新promise对象进行执行 意味着 这个then一旦捕获就说明函数2的定时器执行完毕
            return new Promise((resolve, reject) => {
                setTimeout(function() {
                    console.log('函数3');
                    resolve();
                }, 2000)
            })
        })

理解

  1. pro1创建时,函数1 的定时器就执行了,此时打印函数1, 然后resolve
  2. resolve后 pro1.then()被触发 return一新promise的执行结果 新promise开始被创建执行 输出函数2 然后resolve
  3. resolve后 由于pro1.then方法本就会返回一个新的promise对象 所以可以继续.then 这个.then中捕获的是上一次.then的return值,上一次return值是promise 这个promise创建便执行 resolve为空 所以 第二次.then中捕获的val为undefined, 紧接着 又一次return一个新promise的执行结果 新promise开始被创建执行 输出函数3

综合

<script>
        const p1 = new Promise(function(resolve, reject) {
            setTimeout(function() {
                console.log('定时器1');
                resolve();
            }, 2000);
        });

        function p2() {
            return new Promise(function(resolve, reject) {
                setTimeout(function() {
                    console.log('定时器2');
                    resolve();
                }, 2000);
            });
        }

        function p3() {
            return new Promise(function(resolve, reject) {
                setTimeout(function() {
                    console.log('定时器3');
                    resolve();
                }, 2000);
            });
        }

        function p4() {
            return new Promise(function(resolve, reject) {
                setTimeout(function() {
                    console.log('定时器4');
                    resolve();
                }, 2000);
            });
        }

        p1.then(() => {
            return p2();
        }).then(() => {
            return p3();
        }).then(() => {
            return p4();
        })
    </script>
上一篇:微信小程序 - 云开发data exceed max size 解决方案


下一篇:前端-promise的使用