ES6基础--Promise

一、什么是Promise
1.Promise有什么
先打印到控制台上
console.dir(Promise)
在这里插入图片描述
可以看到原型有构造函数、catch、then、finally、Symbol(ES6原始数据类型,解决命名冲突问题),本身有all、reject、resolve、race函数,与其他构造函数没什么大的区别

new个实例看看

    var p = new Promise((resolve, reject) => {
        // 模拟调用接口
        setTimeout(() => {
            console.log('调用接口');
            resolve('返回数据')
        }, 2000)
    })

看到Promise需要传入resolve,reject两个回调函数,用于执行执行成功和执行失败两种情况

二、Promise可以做什么
1、Promise的异步操作
Promise可以用来执行异步操作,这是Promise最常见的用法,比如上面的setTimeout,在实际的开发中可以替换为下发到后台的接口,调用接口成功回调resolve,调用接口失败回调reject

2、Promise的链式调用
原型中有then,catch这些函数,所以可以执行链式调用
举个栗子

    var p = new Promise((resolve, reject) => {
        // 模拟调用接口
        setTimeout(() => {
            console.log('调用接口');
            resolve('返回数据')
        }, 2000)
    }).then(() => {
        console.log('调用接口后');
    }).finally(() => {
        console.log('调用接口完成');
    })

3、Promise简化回调
先看下面的代码

    function runAsync(resolve) {
        // 模拟调用接口
        setTimeout(() => {
            console.log('调用接口');
            resolve('返回数据')
        }, 2000)
    }

    runAsync((data) => {
        console.log(data);
    })

我写了一个回调函数,作为参数传入runAsync,等接口调用完成后执行,不也可以实现回调?感觉还更简洁,那Promise有什么好?

但其实这只是一种特殊情况,如果callback本身是一个异步操作呢?还要给callback传一个callback2?这样一点也不优雅,代码层层回调也很容易让人看不懂,而Promise的优势在于,可以在then方法中继续写Promise对象并返回,然后继续调用then来进行回调操作
像是这样

    function runAsync1() {
        var p = new Promise((resolve, reject) => {
            // 模拟调用接口
            setTimeout(() => {
                console.log('调用接口1');
                resolve('返回数据')
            }, 2000)
        })
        // 返回的是Promise对象
        return p
    }
    function runAsync2() {
        var p = new Promise((resolve, reject) => {
            // 模拟调用接口
            setTimeout(() => {
                console.log('调用接口2');
                resolve('返回数据')
            }, 2000)
        })
        // 返回的是Promise对象
        return p
    }
    function runAsync3() {
        var p = new Promise((resolve, reject) => {
            // 模拟调用接口
            setTimeout(() => {
                console.log('调用接口3');
                resolve('返回数据')
            }, 2000)
        })
        // 返回的是Promise对象
        return p
    }

    runAsync1()
        .then((data) => {
            console.log(data);
            return runAsync2()
        })
        .then((data) => {
            console.log(data);
            return runAsync3()
        })
        .then(function (data) {
            console.log(data);
        });

在这里插入图片描述

这样接口调用能够老老实实地按接口调用的顺序返回,代码更简洁,代码维护起来更方便

4、reject和catch
上面说了resolve,现在讲reject,then函数可以传入两个回调函数,像这样

getNum().then(
        (data) => {
            console.log(data);
            console.log(aaa);
        },
        (data) => {
            console.log(data);
        }
    )

和resolve用法一样,不多赘述

catch的用法是作为链式操作,和then的第二个参数reject作用一样

    function getNum() {
        var p = new Promise((resolve, reject) => {
            const num = Math.ceil(Math.random() * 10)
            if (num <= 5) {
                resolve('数字=' + num)
            } else {
                reject('数字=' + num + '数字太大了')
            }
        })
        return p
    }

    getNum().then(
        (data) => {
            console.log(data);
        }
        // (data) => {
        //     console.log(data);
        // }
    )
    .catch((data) => {
        console.log(data);
    })

但catch还有另一个用法,就是当代码出错时捕获,reject无法做到

    getNum().then(
        (data) => {
            console.log(data);
            console.log(aaa);
        }
        // (data) => {
        //     console.log(data);
        // }
    )
    .catch((error) => {
        console.log(error.message);
    })

这里提一个小建议:
能够预判到的异常,如数字超出范围的,用reject,不能预判的异常,如代码漏洞,接口报400的,用catch

finally函数不多讲,也提一个小建议:
finally执行resolve和reject都要执行的操作,如数据的赋值,接口返回的标志

三、Promise的常用函数
上面说的都是比较常见的函数,下面说下Promise的独有的方法
1、Promise.race()
race,意为赛跑,把多个Promise的实例做列表,作为参数传入,只要有一个执行完成,就返回
举个栗子

    var p1 = new Promise((resolve, reject) => {
        // 模拟调用接口
        setTimeout(() => {
            console.log('调用接口1');
            resolve('返回数据1')
        }, Math.random() * 1000)
    })

    var p2 = new Promise((resolve, reject) => {
        // 模拟调用接口
        setTimeout(() => {
            console.log('调用接口2');
            resolve('返回数据2')
        }, Math.random() * 1000)
    })

    var p3 = new Promise((resolve, reject) => {
        // 模拟调用接口
        setTimeout(() => {
            console.log('调用接口3');
            resolve('返回数据3')
        }, Math.random() * 1000)
    })

    Promise.race([p1, p2, p3])
    .then((data) => {
        console.log(data);
    })

在这里插入图片描述

这里用random模拟接口返回的快慢,then函数resolve的参数只有一个,只处理第一个返回的数据,但其他异步操作并没有中断,而是继续执行

2、Promise.all()
和race不同,all()需要所有异步操作全部成功完成,才执行resolve, 只要有一个执行失败就会执行reject
resolve返回的也不一样,是每个异步操作调用resolve的结果

    var p1 = new Promise((resolve, reject) => {
        // 模拟调用接口
        setTimeout(() => {
            console.log('调用接口1');
            resolve('返回数据1')
        }, Math.random() * 1000)
    })

    var p2 = new Promise((resolve, reject) => {
        // 模拟调用接口
        setTimeout(() => {
            console.log('调用接口2');
            resolve('返回数据2')
        }, Math.random() * 1000)
    })

    var p3 = new Promise((resolve, reject) => {
        // 模拟调用接口
        setTimeout(() => {
            console.log('调用接口3');
            resolve('返回数据3')
        }, Math.random() * 1000)
    })

    Promise.all([p1, p2, p3])
    .then((data) => {
        console.log(data);
    })

在这里插入图片描述

3、race和all的用法
当有多个异步操作,但只需要一个接口返回时,可以用race,比如请求一个资源,后台执行时间不确定时,当第一次返回,直接用第一次返回的数据,多次请求没有返回的话,报资源请求超时错误抛出
当有多个异步操作。但需要全部接口返回时,可以用all,比如请求一个大规模的数据,一个接口携带的数据量不够,可以分批多次下发,接口全部返回才展示到界面上

四、一些需要注意的点
后面想到再补充

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值