promise

promise是一种异步编程解决方案,回调函数也可以解决异步编程问题,如果层次过深,会出现回调地狱问题
  • 下面的代码,先打印2再打印1 因为定时器是异步执行的,互不影响,所以时间短的先执行
        function fn1() {
            setTimeout(function () {
                console.log(1);
            }, 1000)
        }
        function fn2() {
            setTimeout(function () {
                console.log(2);
            }, 500)
        }
        fn1();
        fn2();
  • 下面的代码,先打印1再打印2,回调函数也可以解决异步编程问题,
function fn1(fn) {
            setTimeout(function () {
                console.log(1);
                fn();
            }, 1000)
        }
        function fn2() {
            setTimeout(function () {
                console.log(2);
            }, 500)
        }
        fn1(fn2);
  • 回调函数虽然可以解决异步编程问题,但是如果层次过深,会出现回调地狱问题
        function fn3() {
            setTimeout(function () {
                console.log(3);
                setTimeout(function () {
                    console.log(2);
                    setTimeout(function () {
                        console.log(1);
                    }, 1000)
                }, 1000)
            }, 100);
        }
        fn3();
  • promise是一个对象,通过new promise来创建对象
  • 创建promise对象,promise需要接收一个函数作为参数,作为参数的函数有两个参数 resolve,reject 这两个参数也是函数
  • promise对象有三种状态:进行中(pending),成功(fullfilled),失败(rejected)
  • 调用resolve方法等价于调用then方法的第一个参数,调用了reject方法,等价于调用then方法的第二个参数
  • then 方法可以接收两个函数作为参数,第一个作为参数的函数,执行成功状态的回调,第二个作为函数的参数,执行失败状态的回调
let p = new Promise(function (resolve, reject) {
            resolve();//调用resolve方法等价于调用then方法的第一个参数
        });

        p.then(function () {
	        //成功
            console.log(1);  //1
        }, function () {
           ///失败
            console.log(2);
        });
        let p = new Promise(function(resolve,reject){
            setTimeout(function(){
                resolve(100);//可以传参,成功状态,所以执行then方法的第一个作为参数的函数
               //reject(); //失败状态
            },1000);
        });

        p.then(function(data){//在这里接收参数
        console.log(data);

        },function(data){
        console.log(data);
        });
  • promise解决异步回调问题
 function fn() {
            let p = new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log("我的定时器是1s");
                    resolve();//成功
                }, 1000);
            });
            return p;
        }
        function fn1() {
            setTimeout(() => {
                console.log("我的定时器是0.5s");
            }, 500);
        }

        fn().then(fn1);//调用fn函数返回Promise对象
  • then()方法
    • then方法可以接收两个函数作为参数
    • 第一个作为参数的函数:成功状态的回调
    • 第二个作为参数的函数:失败状态的回调

注意:then方法会返回一个新的promise,由于返回值是promise,所以then方法可以实现连缀效果。then方法若只接收了一个参数,则这个参数是成功回调。
then方法的第一个参数函数的返回值问题:
1)若返回值是一个非promise,则这个数据会作为参数传递给第二个then

        let p = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve();//成功
            }, 1000);
        });
        p.then(() => {
            return "hello";
        }).then((data) => {
            console.log(data);//hello
        });

2)若返回值是一个promise,则第二个then状态的改变取决于这个promise
示例:利用promise解决异步回调问题

function fn1(){
            const p = new Promise((resolve,reject)=>{
                setTimeout(()=>{
                    resolve("我是1s");
                },1000);
            });
            return p;
        }
        function fn2(){
            const p = new Promise((resolve,reject)=>{
                setTimeout(()=>{
                    resolve("我是0.5s");
                },500);
            });
            return p;
        }
        function fn3(){
            const p = new Promise((resolve,reject)=>{
                setTimeout(()=>{
                    resolve("我是0.1s");
                },100);
            });
            return p;
        }

        fn1().then((data)=>{
            console.log(data);
            return fn2();
        }).then((data)=>{
            console.log(data);
            return fn3();
        }).then((data)=>{
            console.log(data);
        });
 function fn(num) {//封装,把变量提取出来
            const p = new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log(num);
                    resolve();
                }, 1000);
            });
            return p;
        };

        fn(1).then(() => {
            return fn(2);
        }).then(() => {
            return fn(3)
        }).then(()=>{
            console.log("over");
        })
  • promise的异常处理:catch方法
  • 捕获,catch方法可以捕获promise执行过程中的错误,也可以捕获promise的失败状态
  • catch也需要接收一个函数作为参数
  • 由于catch既可以接收promise的失败状态,又可以捕获promise中的代码异常信息,所以推荐:在then中接收成功结果,在catch中接收失败和异常结果
        let p = new Promise((resolve,reject)=>{
            console.log(1);   
            // resolve("ok");
            throw new Error("错误");
            // reject("no");
        });

        p.then((data)=>{
            console.log(data);
        }).catch((err =>{
            console.log(err);
        }));
  • finally方法
    • 不管promise的状态是成功还是失败,均会执行finally中的代码
let p = new Promise((resolve,reject)=>{
            if(true){
                resolve(1);
            }else{
                reject(2);
            }
        });

        p.then(data=>{
            console.log(data);
        }).catch(err=>{
            console.log(err);
        }).finally(()=>{
            console.log("开始下一步");
        });
  • Promise.all()方法
    • all方法可以把多个promise实例包装成一个新的promise实例
 let p1 = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(1);
            }, 1000);
        })

        let p2 = new Promise((resolve, reject) => {
            setTimeout(() => {
                // reject(2);
                resolve(2);
            }, 2000);
        });
        console.time();
        const p = Promise.all([p1, p2]);
        p.then((data) => {
            //都为成功状态才会执行
            console.log(data);//返回数组[1,2]
            console.timeEnd();//2s
        }).catch(err => {
            console.log(err);
        });
  • 总结:上面示例中,all方法将p1和p2封装为了一个新的promise实例,这个新的promise实例的状态取决于p1和p2的状态,分两种情况:
    • 第一种情况:若p1和p2都变为成功状态,则新的promise也会变成成功状态,并且,会把p1和p2的成功的结果封装为数组在新的promise中收到
    • 第二种情况:若p1或者p2有一个变为了失败状态,则新的promise会立即变为失败状态
  • Promise.race()方法
    • race方法也会将多个promise封装为一个新的promise实例。新的promise实例的改变取决于最快发生改变的那个promise的状态。
let p1 = new Promise((resolve, reject) => {
           let img = new Image();//实例化一个img对象
           img.src = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1601216995406&di=06e5480673224233af7409be12eba521&imgtype=0&src=http%3A%2F%2Fc.hiphotos.baidu.com%2Fzhidao%2Fpic%2Fitem%2F3ac79f3df8dcd100501e1ae0708b4710b8122f75.jpg";
           img.title = "图片1";
           img.onload = function () {//图片加载完毕
               resolve(img);
           }
           img.onerror = function () {//图片加载失败
               reject("图片加载失败!!!");
           }
       });
       let p2 = new Promise((resolve, reject) => {
           let img = new Image();//实例化一个img对象
           img.src = "";
           img.title = "图片2";
           img.src = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1601217068347&di=b21f50971c496ce7ecef47944753f1a4&imgtype=0&src=http%3A%2F%2Fa2.att.hudong.com%2F84%2F39%2F01300000957523128228398329921.jpg";
           img.onload = function () {//图片加载完毕
               resolve(img);
           }
           img.onerror = function () {//图片加载失败
               reject("图片加载失败!!!");
           }
       });

       let p = Promise.race([p1, p2]);
       p.then(data => {
           console.log(data);
       }).catch(err => {
           console.log(err);
       });
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值