JS-Promise使用

Promise出现原因

由于传统回调函数的方式写代码时,后一个异步请求发起依赖于当前请求的结果,。。。然后就产生了回调地狱,主要表现在代码的结构凌乱,不好写,不好阅读,不好维护,Promise的出现具有重大的意义,分析Promise的实现,可以更深层次的摸清函数的写法,参数的传递等JS规则

Promise常规使用

Promise请求有三种状态:pending(未决),resolved(已决),reject(已决),将Promise从未决推向已决后,不能再次改变状态

Promise同步代码结构:new一个Promise,promise里是一个已经内部绑定过的回调函数,该回调函数又由两个函数resolve和reject作为参数,通过resolve([参数])到达resolved状态,reject([参数])到达rejected状态。

Promise异步代码结构(thenable):即then那一部分,then里可注册resolved状态相关的回调函数,参数为resolve(x)中x的内容,比如resolve(19),该回调函数的参数就是19;then里可注册rejected状态相关的回调函数,参数为reject(x)中x的内容,比如reject(19),该回调函数的参数就是19

Promise异步代码结构(catchable):即catch那一部分,和thenable里的rejected状态部分差不多

new Promise((resolve,reject)=>{
    setTimeout(function(){
        // resolve(19)
        reject(19)
    },1000)
}).then(data=>{
    console.log(data)
    console.log("data")
},err=>{
    console.log(err)
    console.log("err1")
}).catch(err=>{
    console.log(err)
    console.log("err2")
})

//输出结果:
1. 如果是resolve(19), 19 data
2. 如果是reject(19), 19 err1

复制代码

上例中,因为在err1所处的回调中已经catch过了,在下一个catch位置前,其实是data为undefined的一个resolved(或fulfilled)的新Promise对象,因此catch不到错误信息了

Promise其他API

resolve

Promise.resolve(13)相当于new Promise(resolve=>{resolve(13)})

reject

Promise.reject(13)相当于new Promise(reject=>{reject(13)})

all

all中传递的是一个iterable类型,数组显然是。all应用场景为,等待所有的异步请球为resolved状态,all的thenable代码才运行;只要有一个rejected,就得去catch了

var t1 = function(){
    return new Promise((resove,reject)=>{
        setTimeout(function(){
            resove(1)
        },1000)
    })
}
var t2 = function(){
    return new Promise((resove,reject)=>{
        setTimeout(function(){
            resove(2)
        },2000)
    })
}

Promise.all([t1(),t2()]).then(data=>{
    console.log(data)//两秒后两个异步请求为resolved,打印结果:(2) [1, 2]
                     //结果是和iterable类型中的请求一一对应的
})
复制代码

race

方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。

Promise async和await

async和await是语法糖,简化了Promise的写法,将请求的同步代码,和回应的一部代码更清晰的展现,增加可阅读性,可以不再使用then

async和await常规使用

async function test(){
    await t1()
    console.log("t1ok")//两秒时刻打印1
    await t2()
    console.log("t2ok")//三秒时刻打印2
}
复制代码

await等待异步响应,下面的代码不会执行,该进程交出控制权,等到异步响应到达,重新掌握控制器,执行后续同步代码,知道下一个await

await 1

注意await只能在async函数中使用,await的到的是Promise的状态数据

注意async函数中的return其实返回的一般是data值或rejected的err值

async function test2(){
    await 1
    //return await 1
}
test2().then(data=>{
    console.log(data)//undefined
})
复制代码

console.log(await 1)发现为1,代码上加上return,相当于把状态数据传递给调用async函数所生成的新Promise,最终结果打印不再是undefined,而是1

async function test2(){
    await 1
}
//官方给的等效代码
async function test2(){
    return Promise.resolve(1).then(data=>undefined)
}
复制代码

async和await如何处理rejected响应

通过try…catch处理

function fn(){
    return new Promise((resolve,reject)=>{
        if(Math.random()<0.5){
            resolve(1)
        }else{
            reject(2)
        }
    })

}
async function test3(){ 
    try {
        var res = await fn()
        console.log(`resolved:${res}`)
    } catch (error) {
        console.log(`rejected:${error}`)
    }
}
test3()
复制代码

多个Promise与reduce的组合

var fun1 = function(){console.log("fun1")}
var fun2 = function(){console.log("fun2")}
var fun3 = function(){console.log("fun3")}

var arrr = [fun1,fun2,fun3]
arrr.reduce((p,f)=>p.then(f),Promise.resolve())
/*打印结果:
fun1
fun2
fun3*/
复制代码

初始值Promise.resolve()将状态推向已决,这使得后续thenable队列中依次运行fun1,fun2,fun3

将setTimeout包装为Promise形式

setTimeout的异步是用旧的回调函数的,现在封装成Promise形式,可以结合await使用了

function delay(ms){
    return new Promise((resolve,reject)=>{
        setTimeout(resolve,ms)
    })
}
async function test4(){ 
    await delay(2000)
    console.log("2秒到了")
}
test4()
复制代码

这个delay函数只有在异步中有效

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享