重温---我熟悉又陌生的promise

62 阅读3分钟

初体验

//promise当中包裹一个异步
//
const p =new Promise((resolve,reject)=>{
    setTimeout(()=>{
        if(){
        //成功调用resolve,且可以将promise对象的状态设置为成功
            resolve(可以传递参数)
        }else{
         //成功调用reject,且可以将promise对象的状态设置为失败
            reject(可以传递参数)
        }
    },1000)
})

p.then((value)=>{
    //成功的回调   
},(reason)=>{
    //失败的回调
})

Promise封装ajax请求

const p=new Promise((resolve,reject)=>{
    const xhr=new XMLHttpResquest()
    xhr.open('get','')
    xhr.send()
    xhr.onreadystatechange=function(){
        if(xhr.readyState===4){
            if(xhr.status>=200&&xhr.status<300){
                //成功请求
                resolve()
            }else{
                //输出失败状态码
                reject()
            }
        }
    }
}).then(()=>{
    //成功的回调
},()=>{
    //失败的回调
})

回顾await和axios

await 原生

const fun=async function(){
       await new Promise((resolve,reject)=>{
        const xhr=new XMLHttpResquest()
        xhr.open('get','')
        xhr.send()
        xhr.onreadystatechange=function(){
            if(xhr.readyState===4){
                if(xhr.status>=200&&xhr.status<300){
                    //成功请求
                    resolve()
                }else{
                    //输出失败状态码
                    reject()
                }
            }
        }
    }).then(()=>{
        //成功的回调
    },()=>{
        //失败的回调
    })
}

await能够接收promise对象,await本身是异步的,是一种处理异步任务的机制,在函数当中能够使一个整体函数变成同步,从上到下一次执行代码

//vue当中常写
封装:
import axios from "axios";

// //请求地址
let baseUrl = '/api'
Vue.prototype.$baseUrl = 'http://com.cn'
axios.defaults.baseURL = baseUrl

Vue.prototype.$http = (url, method, data, async, fun) => {
    axios({
        url: url,
        method: method,
        data: JSON.stringify(data),
        async: async
    }).then(resp => {

        fun(resp.data)
    }).catch(err => {
        console.log(err)
    })
}

使用:
async fun(){
    let res=await this.$http('','').catch((err))
    
    
}

promise

状态--PromiseState

pending变为resolved/rejected,只有这两种状态,且promise只能改变一次,都只会有一个结果数据,成功的一般称为value,失败的为reason

值--PromiseResult

保存成功失败的结果,只有reject和resolve可以修改

promise基本流程

image.png

promise方法

Promise.all

如果所有都是成功状态就返回成功,若有失败就返回失败

成功: image.png

失败:

image.png

let p1=new Promise((resolve,reject)=>{
    resolve('ok')
})

let p2=Promise.resolve('')

const result=Promise.all([p1,p2])

Promise.race

第一返回的promise对象的状态决定,成功race就返回成功,反之

promise当中的关键问题

  • 可以为一个promise指定多个then,当状态发生改变的时候都会被调用
  • 改变promise状态和指定回调函数谁先谁后,都有可能
let p =new Promise((resolve,reject)=>{
    resolve(ok)//改变状态,这个先?
})

//这个先?
p.then(value=>{

},reason)

//状态先改变的情况:就是执行器当中是一个同步任务的时候
let p =new Promise((resolve,reject)=>{
    resolve(ok)这个先
})
p.then(value=>{
},reason)

//回调函数先的情况:就是执行器当中是一个异步任务的时候
let p =new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve(ok)
    },1000)
})
这个先
p.then(value=>{
},reason)
  • 只有状态改变之后才能拿到数据

  • 链式调用

//在p成功之后又继续执行promise,如果这个promise成功,则p.then返回成功
let p =new Promise((resolve,reject)=>{
    resolve(ok)这个先
})
p.then(value=>{
    return new Promise((resolve,reject)=>{
        
    })
},reason)
  • 异常穿透(只在最后指定catch)
let p =new Promise((resolve,reject)=>{
        resolve(ok)
})

//可以直接输出11,22,33,
p.then(value=>{
    //throw '失败' //不用在下一个then里面指定reject,他会跳到catch直接catch异常
    console.log('111')
}).then(value=>{
    console.log('222')
}).then(value=>{
    console.log('333')
}).catch(reason=>{
    console.warn(reason)
})

promise与事件循环

事件循环(在我的另外一篇文章当中有详细说明捏小红书一面凉经(二) - 掘金 (juejin.cn))简单来说就是代码执行大致分为同步和异步,同步代码放入执行栈立即执行,而异步代码会放入宿主环境种,待异步代码等待结束之后会放入任务队列,当执行栈当中的代码都执行完成之后,会到任务队列当中去寻找是否有排队的代码,有就执行,执行完成之后又会到任务队列当中询问,这样不断询问的过程就叫做事件循环

而异步当中又会分为宏任务和微任务,宏任务是指由宿主环境发起的比如定时器,而微任务是由js引擎发起的任务,比如script、promise

而我们要注意promise本身是同步的,是他的回调函数.catch、.then是异步的