Promise用法

Promise

Promise有三种状态 

  • 待定(pending): 初始状态,既没有被兑现,也没有被拒绝。
  • 已兑现(fulfilled): 意味着操作成功完成。
  • 已拒绝(rejected): 意味着操作失败。

    Promise的状态是不可逆的,只有pending -> fulfilled, 或者pending -> rejected,成功或失败后不能改变其状态。

  Promise和then是配套出现,then中有两个参数,第一个表示成功,第二个表示失败

new Promise((resolve, reject) => {

    resolve('成功') // 这是通知执行的作用

    reject('失败')  // 无效,已经是fulfilled状态了,不能再改变

 }).then(

  msg => {console.log(msg)},

  error=>{console.log(error)}

 )
// 结果: 成功

 

** 微任务、宏任务混合🌰

console.log(1)
new Promise(resolve => {
    setTimeout(() =>{
        resolve(3)
    }, 0)
  setTimeout(() => {
      console.log(5)
  },0)
}).then(result => { 
  console.log(result) 
}).then(() => { 
  console.log(4) 
}) 
console.log(2)

执行结果 1 2 3 4 5

我们遇到这种问题首先得把三种任务类型区分开(主任务、微任务、宏任务)。主任务队列执行完之后会去轮询微任务队列,最后再轮询宏任务队列。

setTimeout就是一个宏任务,Promise是微任务。

1 首先顺序执行输出1。

2 同步执行到Promise中,遇到setTimeout(),将它丢进宏任务队列中,所以setTimeout宏任务不执行,resolve也执行不到。

3. 继续向下执行遇到setTimeout,再丢进宏任务队列中。

4. 继续同步执行输出 2

5. 主任务队列执行完,发现没有微任务,所以轮询宏任务,此时有两个宏任务等待执行,按照顺序先进先出,将第一个拿到主任务队列执行。

6. 执行时发现resolve,同步向下执行遇到Promise的第一个then,将它丢进微任务队列,然后再执行又遇到一个then,再丢进微任务队列。

7. 此时主任务队列执行完毕,发现有微任务,先执行微任务,轮询依次输出3和4

8 最后轮询宏任务,输出 5

 

总结: 任务执行优先级  主任务 > 微任务 > 宏任务 。

本例子宏微任务混合,微任务要再宏任务执行之后才会被触发,则宏任务不执行,微任务队列为空,所以要先执行宏任务。

 

知识点1: Promise的then也是一个Promise

打印p2的时候,微任务还未执行,所以是pending(等待)状态 

如果将console放入setTimeout中,就是在微任务执行完之后,就是fulfilled状态

 

知识点2: Promise里面 return一个值相当于resolve(),then中的成功回调函数会接收到这个值

 

 

知识点3: 在Promise中封装一个Promise,可以使用类、对象或者直接写一个then方法返回等

 

知识点4:使用Promise封装ajax异步请求

function request() {
     return new Promise((resolve, reject) => {
            resolve('成功!')
    })      
}
request().then(res => {
   console.log(res) 
})

// 结果:成功

 

 

知识点5: 自定义请求错误(如下例子,自已封装了一个ajax请求,请求过程中会有各种类型的错误,自定义了两个错误实例 httpError urlError 用于处理用户请求错误)

class httpError extends Error {
     constructor(msg) {
          super(msg); 
          this.name = 'httpError'
    }
}

class urlError extends Error {
     constructor(msg) {
          super(msg); 
          this.name = 'urlError'
    }
}

function ajax(url) {
  return new Promise((resolve, reject) => {
        if (!/^http/.test(url)) {
            throw new httpError('请求地址错误')
        }
        let xhr = new XMLHttpRequest();
        xhr.open('GET', url)
        xhr.send()
        xhr.onload = function() {
            if(this.status === 200) {
                resolve(JSON.parse(this.response))
             } else if (this.status === 404){
                   reject(new urlError('用户请求路径错误!'))
             } else {
                    reject('请求错误')
             }
        }
    })  
}
ajax('url').then(res => {
  console.log(res)
}).catch(error => {
  if (error instanceof httpError) {
    alert(error)
  } else {
    console.log(error)
  }
}) 

 

最后附上一个Promise题目

function executor(resolve, reject) {
    let rand = Math.random();
    console.log(1)
    console.log(rand)
    if (rand > 0.5)
        resolve()
    else
        reject()
}
var p0 = new Promise(executor);

var p1 = p0.then((value) => {
    console.log("succeed-1")
    return new Promise(executor)
})


var p3 = p1.then((value) => {
    console.log("succeed-2")
    return new Promise(executor)
})

var p4 = p3.then((value) => {
    console.log("succeed-3")
    return new Promise(executor)
})


p4.catch((error) => {
    console.log("error")
})
console.log(2)

留个悬念,分析看看如何执行?

posted @ 2021-07-26 09:44  半暖半夏(。・ω・。)  阅读(264)  评论(0编辑  收藏  举报