第N次学习Promise

236 阅读3分钟

什么是Promise

Promise 是异步编程的一种解决方案: 从语法上讲,promise是一个对象,从它可以获取异步操作的消息;从本意上讲,它是承诺,承诺它过一段时间会给你一个结果。 promise有三种状态:pending(等待态),fulfiled(成功态),rejected(失败态) ;状态一旦改变,就不会再变。创造promise实例后,它会立即执行。

Promise的作用

promise是用来解决两个问题的:

  • 回调地狱,代码难以维护, 常常第一个的函数的输出是第二个函数的输入这种现象
  • promise可以支持多个并发的请求,获取并发请求中的数据

之前写回调的形式

function fn(a,fn2){
    if(a > 1){
        fn2()
    }
}
fn(2,function(){
    console.log("你好")
})
let p = new Promise(((resolve, reject) => {
    //执行一些异步操作
    setTimeout(() => {
        console.log("我执行了")
        resolve("我是成功的")
    },3000)
}))
p.then( (res)=> {
    console.log(res)
},(err) => {
    console.log(err)
})

Promise的构造函数接收一个参数:function(resolve,reject),并且这个函数需要传入两个参数:

  • resolve :异步操作执行成功后的回调函数
  • reject:异步操作执行失败后的回调函数 then中传了两个参数,then方法可以接受两个参数,第一个对应resolve的回调,第二个对应reject的回调

catch的效果和then的第二个函数效果一样,但是在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中。其作用与try-catch一致。

此处写一段链式调用的代码

注意如何在then中返回一个新的Promise,以及两种语法糖的使用

  1. Promise.reslove()

  2. return ...

  3. return new Promise()

let p = new Promise(((resolve, reject) => {
    //执行一些异步操作
    setTimeout(() => {
        var a = 3
        resolve(a)
        // reject(b)
    },3000)
}))
p.then((data) => {
    console.log(data);
    return new Promise((resolve,reject) => {
        var s = "此处执行了数据请求工作,成功"
        resolve(s)
    })
})
    .then((data) => {
        console.log(data);
        return Promise.reject("抛出错误")
    })
    .then((data) => {
        console.log(data);
    },(err) => {
        console.log(err)
        return 1111
    })
    .then((data) => {
        console.log(data);
    })

Promise.all

promise.all 的特点:

  • 入参是个由多个Promise实例组成的数组
  • 返回值是个promise,因为可以使用.then
  • 如果全部成功,状态变为resolved, 并且返回值组成一个数组传给回调
  • 但凡有一个失败,状态变为rejected, 并将error返回给回调
function myPromiseAll(p){
    return new Promise((resolve,reject) => {
        //执行判断
        if(!Array.isArray(p)){
            throw new TypeError("promises must be an array")
        }
        let result = [];
        let count = 0;
        //对p中的Promise对象进行判断
        p.forEach((promise,index) => {
            promise.then((res) => {
                //此处不能用result.push(res),而是通过索引来添加,因为forEach是异步任务,如果用push可能会使得res的顺序错误。Promise.all返回的顺序不会改变。
                result[index] = res
                count++
                //执行判断,当p中的promise对象都执行完成后,将result resolve出去
                count === p.length && resolve(result)
            },(err) => {
                reject(err)
            })
        })
    })
}
//测试
let p1 = Promise.resolve(1),
    p2 = Promise.resolve(2),
    p3 = Promise.resolve(3);

myPromiseAll([p1, p2, p3]).then((res)=>{
    console.log(res, 'res')
}, (err)=>{
    console.log(err, 'err')
})
//[ 1, 2, 3 ] res

实现Promise.race

function myPromiseRace(p){
    return new Promise((resolve,reject) => {
        p.forEach((promise,index) => {
            Promise.resolve(promise).then((value) => {
                resolve(value)
            },(reason) => {
                reject(reason)
            })
        })
    })
}
let p1 = new Promise(((resolve, reject) => {
    setTimeout(() => {
        var a = 1
        resolve(a)
    },1000)
}))
let p2 = new Promise(((resolve, reject) => {
    setTimeout(() => {
        var b = 2
        resolve(b)
    })
}))
let p3 = new Promise(((resolve, reject) => {
    reject(3)
}))
let p = [p1,p2,p3]
myPromiseRace(p).then((res)=> {
    console.log(res)
},(err) => {
    console.log(err)
})

完成forEach里面是异步任务,所以才能用来实现Promise.race