前端知识点-promise


为什么要用promise?

在promise前是用回调函数,当随着回调嵌套的越多会产生回调地狱的问题。

  • 回调地狱是为了让我们代码执行顺序的一种操作(解决异步),但是它会使我们的可读性非常差。

2

3

基本概念 — 买包包示例

<script>
    // promise 承诺 
    // 异步的
    // 声明时状态是待定的,只有两种状态变换,待定->成功状态 和 待定->失败状态,状态都是不可逆转的
    let isForget = false;
    let getLv = new Promise((resolve, reject) => {
      if(isForget){
        let lv = {
          color: 'red',
          price: '¥99'
        }
        resolve(lv)   // 成功状态
      }else{
        let err = new Error('我加班去了,忘记了')
        reject(err)   // 失败状态
      }
    })

    let testFn = function (){
      getLv.then((fulfilled)=>{     // then 表示成功状态
        console.log(fulfilled);
      }).catch((rejectd)=>{         // catach 表示失败状态
        console.log(rejectd.message);
      })
    }
    testFn()
  </script>

promise的链式调用

<script>
    // promise 承诺 
    // 异步的
    // 声明时状态是待定的,只有两种状态变换,待定->成功状态 和 待定->失败状态,状态都是不可逆转的
    let isForget = true;
    let getLv = new Promise((resolve, reject) => {
      if(isForget){
        let lv = {
          color: 'red',
          price: '¥99'
        }
        resolve(lv)   // 成功状态
      }else{
        let err = new Error('我加班去了,忘记了')
        reject(err)   // 失败状态
      }
    })

    let buyLip = (lv)=>{
      let lip = {
        brand: 'w',
        color: 'pink'
      }
      let msg = {
        message: `我买的口红是${lip.brand}搭配我的${lv.color}`,
        lip: lip,
        lv: lv
      }
      return Promise.resolve(msg)
    }

    let testFn = ()=>{
      getLv
      .then(buyLip)
      .then((fulfilled)=>{
        console.log(fulfilled);
      }).catch((rejectd)=>{
        console.log(rejectd.message);
      })

    }
    testFn()

  </script>

手写一个Promise

  • 基本结构
// 基本结构
<script>
    function myPromise (excutor){  // excutor: 传入一个函数作为执行器
    // 第一步 1.执行结构
    let self = this;
    self.status = 'pending';  // 状态
    self.value = null;    // 成功的结果
    self.reason = null;   // 失败的结果

    // 成功的回调
    function resolve(value){
      
    }
    // 失败的回调
    function reject(reason){
     
    }

    // 第三步 3. 执行一遍  也可不加try catch 直接执行  excutor(resolve, reject)
    // 预防出错外面包 try catch
    try{
      // 执行器
      excutor(resolve, reject);
    }catch(err){
      reject(err)
    }
    // 第三步 3. 执行一遍
   }

   // 第二步 2. .then方法 -> 添加到原型链上
   myPromise.prototype.then = function(){
    
   }


   let demo = new myPromise((resolve, reject)=>{
    console.log('wzt');
   })

  </script>
  • 基本功能 promise 1.0 版
 <script>
    function myPromise (excutor){  // excutor: 传入一个函数作为执行器
    // 第一步 1.执行结构
    let self = this;
    self.status = 'pending';  // 状态
    self.value = null;    // 成功的结果
    self.reason = null;   // 失败的结果

    // 第八步 8. 添加缓存数组
    self.onFulfilledCallbacks = [];
    self.onRejectedCallbacks = [];

    // 成功的回调
    function resolve(value){
      // 第四步 4. 判断状态,做相应处理
      if(self.status === 'pending'){
        self.value = value;   // 保存成功的结果
        self.status = 'fulfilled' // 将状态变为成功状态  

        // 第十步 10. 状态改变,依次取出
        self.onFulfilledCallbacks.forEach(item => item(value))
      }
    }
    // 失败的回调
    function reject(reason){
      // 第四步 4. 判断状态,做相应处理
      if(self.status === 'pending'){
        self.reason = reason; // 保存失败的原因
        self.status = 'rejected'

        // 第十步 10. 状态改变,依次取出
        self.onRejectedCallbacks.forEach(item => item(reason))
      }
    }

    // 第三步 3. 执行一遍  也可不加try catch 直接执行  excutor(resolve, reject)
    // 预防出错外面包 try catch
    try{
      // 执行器
      excutor(resolve, reject);
    }catch(err){
      reject(err)
    }
    // 第三步 3. 执行一遍
   }

   // 第二步 2. .then方法 -> 添加到原型链上
   myPromise.prototype.then = function(onFulfilled, onRejected){
      // 第五步 5. 状态改变 => 调用then()
      // 判断传入的是不是一个方法,如果是就用 如果不是就定义一个方法
      onFulfilled = typeof onFulfilled === 'function' ? 
      onFulfilled : function (data) { resolve(data) }

      onRejected = typeof onRejected === 'function' ? 
      onRejected : function (err) { throw err }

      let self = this;
      // 第九步 9. 先添加进去
      if(self.status === 'pending'){
          self.onFulfilledCallbacks.push(onFulfilled);
          self.onRejectedCallbacks.push(onRejected);

      }
   }


   let demo = new myPromise((resolve, reject)=>{
    console.log('wzt');

    // 第六步 6. 尝试异步任务
    setTimeout(()=>{
      resolve(11)
    }, 500)
   })

   //
   demo.then(data => console.log(data))
  </script>

添加链式调用功能 promise 2.0 版

<script>
    function myPromise (excutor){  // excutor: 传入一个函数作为执行器
    // 第一步 1.执行结构
    let self = this;
    self.status = 'pending';  // 状态
    self.value = null;    // 成功的结果
    self.reason = null;   // 失败的结果

    // 第八步 8. 添加缓存数组
    self.onFulfilledCallbacks = [];
    self.onRejectedCallbacks = [];

    // 成功的回调
    function resolve(value){
      // 第四步 4. 判断状态,做相应处理
      if(self.status === 'pending'){
        self.value = value;   // 保存成功的结果
        self.status = 'fulfilled' // 将状态变为成功状态  

        // 第十步 10. 状态改变,依次取出
        self.onFulfilledCallbacks.forEach(item => item(value))
      }
    }
    // 失败的回调
    function reject(reason){
      // 第四步 4. 判断状态,做相应处理
      if(self.status === 'pending'){
        self.reason = reason; // 保存失败的原因
        self.status = 'rejected'

        // 第十步 10. 状态改变,依次取出
        self.onRejectedCallbacks.forEach(item => item(reason))
      }
    }

    // 第三步 3. 执行一遍  也可不加try catch 直接执行  excutor(resolve, reject)
    // 预防出错外面包 try catch
    try{
      // 执行器
      excutor(resolve, reject);
    }catch(err){
      reject(err)
    }
    // 第三步 3. 执行一遍
   }

   // 第二步 2. .then方法 -> 添加到原型链上
   myPromise.prototype.then = function(onFulfilled, onRejected){
      // 第五步 5. 状态改变 => 调用then()
      // 判断传入的是不是一个方法,如果是就用 如果不是就定义一个方法
      onFulfilled = typeof onFulfilled === 'function' ? 
      onFulfilled : function (data) { resolve(data) }

      onRejected = typeof onRejected === 'function' ? 
      onRejected : function (err) { throw err }

      let self = this;

      // // 第九步 9. 先添加进去
      // if(self.status === 'pending'){
      //     self.onFulfilledCallbacks.push(onFulfilled);
      //     self.onRejectedCallbacks.push(onRejected);

      // }

      if(self.status === 'fulfilled'){
        return new myPromise((resolve, reject) => {
          try{
              let x = onFulfilled(self.value);
              // 判断传进来的值是否是一个promise 是的话继续.then(), 否则抛出结果
              x instanceof myPromise ? x.then(resolve, reject) : resolve(x);
          }catch(err){ 
            reject(err)
          }
        })
      }

      if(self.status === 'rejected'){
        return new myPromise((resolve, reject) => {
          try{
              let x = onRejected(self.value);
              // 判断传进来的值是否是一个promise 是的话继续.then(), 否则抛出结果
              x instanceof myPromise ? x.then(resolve, reject) : resolve(x);
          }catch(err){ 
            reject(err)
          }
        })
      }

      if(self.status === 'pending'){
        return new myPromise((resolve, reject) => {
          self.onFulfilledCallbacks.push(()=>{
            let x = onFulfilled(self.value);
            x instanceof myPromise ? x.then(resolve, reject) : resolve(x);
          });
          self.onRejectedCallbacks.push(()=>{
            let x = onRejected(self.value);
            x instanceof myPromise ? x.then(resolve, reject) : resolve(x);
          });
        })
      }

   }

   // 第十一步 11. .catch 方法 -> 添加到原型链上
   myPromise.prototype.catch = function(fn){
    return this.then(null, fn)
   }


// *测试用例*******************************************************************************
  //  let demo = new myPromise((resolve, reject)=>{
  //   console.log('wzt');

  //   // 第六步 6. 尝试异步任务
  //   setTimeout(()=>{
  //     resolve(11)
  //   }, 500)
  //  })

  //  //
  //  demo.then(data => console.log(data))


  let isForget = true;
    let getLv = new myPromise((resolve, reject) => {
      if(isForget){
        let lv = {
          color: 'red',
          price: '¥99'
        }
        resolve(lv)   // 成功状态
      }else{
        let err = new Error('我加班去了,忘记了')
        reject(err)   // 失败状态
      }
    })

    let buyLip = (lv)=>{
      let lip = {
        brand: 'w',
        color: 'pink'
      }
      let msg = {
        message: `我买的口红是${lip.brand}搭配我的${lv.color}`,
        lip: lip,
        lv: lv
      }
      return new myPromise(function(y, n){
        y(msg)
      })
    }

    let testFn = ()=>{
      getLv
      .then(buyLip)
      .then((fulfilled)=>{
        console.log(fulfilled);
      }).catch((rejectd)=>{
        console.log(rejectd.message);
      })

    }
    testFn()
  </script>

输出结果


文章作者: Zetai Wei
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Zetai Wei !
评论
  目录