初始Promise--promise基本用法

143 阅读7分钟

一、ES6之前异步请求的处理方式

Promise期约或者称承诺一直是面试的高频考点,非常重要,也是ES6非常重要的一个新特性,那么为什么会有期约呢。当我们调用异步函数时,是没有办法直接拿到返回结果的,因为是异步的。所以需要使用回调函数,成功时回调请求成功的函数,失败时回调请求失败的函数。但是这样非常麻烦,所以为了避免这些弊端,推出了Promise,规范好了所有代码的编写逻辑。

  // 模拟网络请求
        function requestData(url,sucesscallback,losemessage){
            setTimeout(()=>{
              if(url==="coderwhy"){
                sucesscallback()
              }
              else{
                losemessage()
              }
        //    该函数异步,是不可以return的,

            },3000)
        }
        // main.js
        requestData("coderwhy",(res)=>{
            console.log("请求成功")
        },(err)=>{
            console.log("请求失败")
        })
弊端:

1> 如果是我们自己封装的requestData,那么我们在封装的时候必须要自己设计好callback名称, 并且使用好。
2> 如果我们使用的是别人封装的requestData或者一些第三方库, 那么我们必须去看别人的源码或者文档, 才知道它这个函数需要怎么去获取到结果

二、Promise的基本使用--实现一个基础的异步请求

如下代码所示,模拟一个异步请求,当url传入,异步请求的代码会被放入excutor中,excutor拿到url,开始运行,如果结果是正确,则请求成功,回调promise.then中成功的函数,如果结果是非正确,则请求失败,回调promise.then中失败的函数,即第二个函数,或者是promise,catch()。

// request.js
function requestData(url,) {
  // 异步请求的代码会被放入到executor中
  return new Promise((resolve, reject) => {
    // 模拟网络请求
    setTimeout(() => {
      // 拿到请求的结果
      // url传入的是coderwhy, 请求成功
      if (url === "coderwhy") {
        // 成功
        let names = ["abc", "cba", "nba"]
        resolve(names)
      } else { // 否则请求失败
        // 失败
        let errMessage = "请求失败, url错误"
        reject(errMessage)
      }
    }, 3000);
  })
}

// main.js
const promise = requestData("coderwhy")
promise.then((res) => {
  console.log("请求成功:", res)
}, (err) => {
   console.log("请求失败:", err)
})

  // 传入的这个函数, 被称之为 executor
       // > resolve: 回调函数, 在成功时, 回调resolve函数
        // >reject: 回调函数, 在失败时, 回调reject函数
       const promise = new Promise((resolve,rejected)=>{
        // 异步请求的代码会被放入exeutor中
       rejected("errmessage")//这里的参数会作为then中成功的回调函数的参数传过去
       })
             
  // then方法传入的回调函数两个回调函数:
  // > 第一个回调函数, 会在Promise执行resolve函数时, 被回调
  // > 第二个回调函数, 会在Promise执行reject函数时, 被回调
       promise.then((res)=>{
        console.log("请求成功:"+res)//res=sucess
       },(err)=>{
        console.log("请求失败:"+err)
    })

三、Promise的三种状态

// 注意: Promise状态一旦确定下来, 那么就是不可更改的(锁定)
new Promise((resolve, reject) => {
  // pending状态: 待定/悬而未决的
  console.log("--------")
  reject() // 处于rejected状态(已拒绝状态)
  resolve() // 处于fulfilled状态(已敲定/兑现状态)
  console.log("++++++++++++")
}).then(res => {
  console.log("res:", res)
}, err => {
  console.log("err:", err)
})

四、promise的resolve参数

const promise = new Promise((resolve,rejected)=>{
       resolve( new Promise((resolve,rejected)=>{
          resolve("aaaaa")
       }))//这里的参数会作为then中成功的回调函数的参数传过去
    //    resolve(参数)
 //  *  1> 普通的值或者对象  pending -> fulfilled
 //  *  2> 传入一个Promise
 //  *    那么当前的Promise的状态会由传入的Promise来决定
 //  *    相当于状态进行了移交
       })
  //  *  3> 传入一个对象, 并且这个对象有实现then方法(并且这个对象是实现了thenable接口)
 //  *    那么也会执行该then方法, 并且又该then方法决定后续状态
   new Promise((resolve, reject) => {
   pending -> fulfilled
  const obj = {
    then: function(resolve, reject) {
      // resolve("resolve message")
      reject("reject message")
    }
  }
  resolve(obj)
}).then(res => {
  console.log("res:", res)
}, err => {
  console.log("err:", err)
})

五、Promise对象方法-then方法。

then方法是Promise对象上的一个方法:它其实是放在Promise的原型上的 Promise.prototype.then

// 1.then方法传入的回调函数两个回调函数:
  // > 第一个回调函数, 会在Promise执行resolve函数时, 被回调
  // > 第二个回调函数, 会在Promise执行reject函数时, 被回调
   promise.then((res)=>{
        console.log("请求成功:"+res)//res=sucess
       },(err)=>{
        console.log("请求失败:"+err)
    })
// 2.then方法可以被多次调用
  promise.then((res)=>{
    console.log("res2:",res)
  })
  promise.then((res)=>{
    console.log("res3:",res)
  })
//  3.then方法可以被链式调用promise.then().then().then()
  promise.then((res)=>{
   return "11111"//会返回一个新的promise,相当于返回的是resolve("11111") 没有写返回值,相当于return:undefined
   //不管返回的是普通值,还是对象还是promise,都相当于返回了一个new promise(),由这个promise的状态决定后面一个then的回调状态.
  }).then(res=>{
    console.log("res3:",res)
  })
// 4.then方法可以后面紧跟catch方法.
  promise.then(res => {
  return new Promise((resolve, reject) => {
      reject("then rejected status")
  })
//   throw new Error("error message")
}).catch(err => {
  console.log("err:", err)//内部在实现时,实际上在执行时catch传入的是第一个promise的异常捕获.
//   如果第一个promise没有异常抛出,则catch会传入前面的返回的promise的异常.
})

六、Promise的catch方法

// 1.当executor抛出异常时, 也是会调用错误(拒绝)捕获的回调函数的
promise.then(undefined, err => {
  console.log("err:", err)
  console.log("----------")
})

// 2.通过catch方法来传入错误(拒绝)捕获的回调函数
// promise/a+规范
promise.catch(err => {
  console.log("err:", err)
})
promise.then(res => {
  return new Promise((resolve, reject) => {
    reject("then rejected status")
  })
  throw new Error("error message")
}).catch(err => {
  console.log("err:", err)//内部在实现时,实际上在执行时catch传入的是第一个promise的异常捕获.
})
// 3.catch方法的返回值
const promise = new Promise((resolve, reject) => {
  reject("111111")
})

promise.then(res => {
  console.log("res:", res)
}).catch(err => {
  console.log("err:", err)
  return "catch return value"//catch里面也是返回一个新的promise,除非抛出异常会调用后面的catch,否则还是调用后面的then方法.
}).then(res => {
  console.log("res result:", res)
}).catch(err => {
  console.log("err result:", err)
})

七、promise的对象方法-finaly

const promise = new Promise((resolve, reject) => {
  // resolve("resolve message")
  reject("reject message")
})

promise.then(res => {
  console.log("res:", res)
}).catch(err => {
  console.log("err:", err)
}).finally(() => {
  console.log("finally code execute")
  // 无论promise捕获的异常还是非异常,都会执行finally的代码
})

八、promise中的类方法promise.resolve

/ 类方法Promise.resolve
// 1.普通的值
const promise = Promise.resolve({ name: "why" })
相当于
const promise2 = new Promise((resolve, reject) => {
  resolve({ name: "why" })
})

// 2.传入Promise
const promise = Promise.resolve(new Promise((resolve, reject) => {
  resolve("11111")
}))

promise.then(res => {
  console.log("res:", res)
})

// 3.传入thenable对象
/ 类方法Promise.resolve
// 1.普通的值
const promise = Promise.resolve({ name: "why" })
相当于
const promise2 = new Promise((resolve, reject) => {
  resolve({ name: "why" })
})

// 2.传入Promise
const promise = Promise.resolve(new Promise((resolve, reject) => {
  resolve("11111")
}))

promise.then(res => {
  console.log("res:", res)
})

// 3.传入thenable对象

九、promise中的类方法promise.rejected()

/ const promise = Promise.reject("rejected message")
// 相当于
// const promise2 = new Promsie((resolve, reject) => {
//   reject("rejected message")
// })

// 注意: 无论传入什么值都是一样的
const promise = Promise.reject(new Promise(() => {}))
// 传入promise,直接打印err:promise{pending}
// 传入function,直接返回then:[function:then]
promise.then(res => {
  console.log("res:", res)
}).catch(err => {
  console.log("err:", err)
})

十、promise中的类方法promise.all()

 const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(11111)
  }, 1000);
})

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(22222)
  }, 2000);
})

const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(33333)
  }, 3000);
})

// 需求: 所有的Promise都变成fulfilled时, 再拿到结果
// 意外: 在拿到所有结果之前, 有一个promise变成了rejected, 那么整个promise是rejected
Promise.all([p2, p1, p3, "aaaa"]).then(res => {
//按照存放在数组的顺序输出,与执行的顺序无关。
//全部都是fullilled,会输出所有的执行结果,如果有一个是rejected,then不会执行,只会执行catch,只会返回rejected的结果.(这也是一个弊端。)
  console.log(res)
}).catch(err => {
  console.log("err:", err)
})

十一、promise类方法-allsetted()

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(11111)
  }, 1000);
})

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(22222)
  }, 2000);
})

const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(33333)
  }, 3000);
})

// allSettled
Promise.allSettled([p1, p2, p3]).then(res => {
  console.log(res)
}).catch(err => {
  console.log(err)
})
    结果以数组方式呈现:
   [{status: 'fulfilled', value: 11111}
   {status: "rejected", reason: 22222}
   {status: 'fulfilled', value: 33333}]

十二、promise的类方法-race()

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(11111)
  }, 3000);
})

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(22222)
  }, 500);
})

const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(33333)
  }, 1000);
})

// race: 竞技/竞赛
// 只要有一个Promise变成fulfilled状态, 那么就结束
// 意外: 
Promise.race([p1, p2, p3]).then(res => {
  console.log("res:", res)//以上代码输出结果为res:22222。
}).catch(err => {
  console.log("err:", err)
})

十三、promise的类方法-any()

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    // resolve(11111)
    reject(1111)
  }, 1000);
})

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(22222)
  }, 500);
})

const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(33333)
    // reject(3333)
  }, 3000);
})

// any方法
//至少等到一个resolve,执行then.如果没有resolve,等到所有rejected的执行完毕,全部返回,抛出一个合并的异常。
Promise.any([p1, p2, p3]).then(res => {
  console.log("res:", res)
}).catch(err => {
  console.log("err:", err.errors)
})

好了,以上就是promise的基本使用方法啦,xia一节,我们开始手写promise。