Promise详解

  • Promise 有三个状态:

    • pending准备/挂起阶段
    • resolve成功,调用resolve()
    • reject失败,调用reject()
    • resolveresolve状态是唯一的且不可逆。
  • 基本写法:

       new Promise((resolve,reject)=>{
    // resolve()
    // reject()
       })
    .then(data=>{
    //resolve状态执行这里
    },err=>{
    //reject状态执行这里
    })
    
  • .then

    • 返回值也是一个Promise,且默认返回的Promise的状态为resolve
  • 封装一个Ajax请求

    ajax(`http://localhost:3000`)
        .then(res => {
            console.log(res.message)
            return ajax(`http://localhost:3000/date`)
        })
        .then(res=>{
            console.log(res)
        })
    
    function ajax(url) {
        return new Promise((resolve, reject) => {
            const xhr = new XMLHttpRequest()
            xhr.open('GET', url)
            xhr.send()
            xhr.onload = function () {
                if (this.status === 200) {
                    resolve(JSON.parse(this.response))
                } else {
                    reject(new Error('请求失败'))
                }
            }
            xhr.onerror = function () {
                reject(new Error('请求失败'))
            }
        })
    }
    
  • 封装一个jQeury.Ajax请求

    ajax(`http://localhost:3000`)
        .then(res => {
            console.log(res.message)
            return ajax(`http://localhost:3000/date`)
        })
        .then(res=>{
            console.log(res)
        })
    
    function ajax(url) {
        return new Promise((resolve, reject) => {
            $.ajax({
                url,
                type: 'get',
                success: resolve,
                error: reject
            })
        })
    }
    
  • axios因为自身就用Promise封装,所以直接写就可以了

        axios.get('http://localhost:3000')
        .then(res => {
            console.log(res.data.message)
            return axios.get('http://localhost:3000/date')
        })
        .then(res => {
            console.log(res.data)
        })
    
  • Promise.all

    • 批量处理Promise,返回值为resolve的值组成的数组
        const baseUrl = `https://game.gtimg.cn/images/lol/act/img/js/`
    
        //请求英雄列表
        function getHeroList(url) {
            return axios.get(url)
        }
    
        //请求单个英雄资料
        function getHeroById(url, id) {
            return axios.get(`${url}hero/${id}.js`)
        }
    
        getHeroList(baseUrl + 'heroList/hero_list.js')
            .then(res => {
                const arr = []
    
                for (item of res.data.hero) {
                    arr.push(getHeroById(baseUrl, item.heroId))
                }
                return Promise.all(arr)
            })
            .then(res => {
                for (item of res){
                    console.log(item.data.hero);
                }
            })
    
  • Promise.all解决错误的方法

    • 一旦遇到任意一个Promisereject状态,并且这个Promise没有catch,那么立即停止批量行为并返回将自身变为reject状态;而如果这个Promisecatch,则不会停止批量行为,但是会返回一个undefined,因为这个Promiserejectcatch,默认返回的是一个resolvePromise,但是不带有数据。
    let p1 = new Promise((resolve, reject) => {
        setTimeout(resolve(1), 1000)
    })
    let p2 = new Promise((resolve, reject) => {
        setTimeout(resolve(2), 2000)
    })
    let p3 = new Promise((resolve, reject) => {
        reject(3)
    })
        .catch(reason=>{
            console.log(3)
        })
    let p4 = new Promise((resolve, reject) => {
        setTimeout(resolve(4), 4000)
    })
    let p5 = new Promise((resolve, reject) => {
        setTimeout(resolve(5), 5000)
    })
    
    Promise.all([p1, p2, p3, p4, p5])
        .then(res => {
                console.log(res)
            }
        )
        .catch(err => {
            console.log(err)
        })
    
        //输出结果 : [1,2,undefined,4,5]
    
  • Promise.AllSettled

    • 用法与Promise.all大致相同,只不过reject状态的Promise不会停止批量操作,且得到的数组中每一项都会有一个status属性来记录是否状态。
  • Promise.race

    • 参数也是Promise数组,但是返回值是一个Promise,它是最早变为resolve状态的那个Promise
  • 语法糖 async&await

    • 下面的例子中,三者的写法是等价的。如果返回的值是直接量,async会将函数包装为一个resolve状态的Promise
       async function test1() {
            return 'async test'
        }
    
        function test2() {
            return Promise.resolve('Promise.resolve test')
        }
    
        function test3() {
            return new Promise(resolve => {
                resolve('new Promise test')
            })
        }
    
        console.log(test1())
        console.log(test2())
        console.log(test3())
        /*
        Promise { 'async test' }
        Promise { 'Promise.resolve test' }
        Promise { 'new Promise test' }
        */
    
    
    • await等待一个表达式返回的值,如果返回的值为直接量,await会利用Promise.resolve把它包装为一个Promise;如果返回的值为Promise,那么不会做处理;表达式是异步的,则会等待异步完成之后,再往下面进行;如果表达式是同步的,则会立即返回。
    function test1(n) {
        return new Promise(resolve => {
            setTimeout(function () {
                resolve(n + 1)
            }, 1000)
        })
    }
    
    function test2(n) {
        return new Promise(resolve => {
            setTimeout(function () {
                resolve(n + 2)
            }, 2000)
        })
    }
    
    function test3(n) {
        return new Promise(resolve => {
            setTimeout(function () {
                resolve(n + 3)
            }, 3000)
        })
    }
    
    async function main() {
        const n1 = await test1(1)
        console.log(n1) //2
        const n2 = await test2(n1)
        console.log(n2) //4
        const n3 = await test3(n2)
        console.log(n3) //7
    }
    
    main()
    
  • 推荐边城老师的理解 JavaScript 的 async/await

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值