聊一聊Promise

ES6中的Promise

什么是Promise

Promise是异步编程的一种解决方案。

使用场景:一般情况是有异步操作时,使用Promise对这个异步操作进行封装

网络请求的回调地狱

多层请求的嵌套

$.ajax('url1', function (data1) {
    $.ajax(data1['url2'], function (data2) {
      $.ajax(data2['url3'], function (data3) {
        $.ajax(data3['url4'], function (data4) {
          console.log(data4);
        })
      })
    })
  })

代码不容易维护,复杂。

使用Promise就可以解决上面的问题,用优雅的方式来处理异步操作。

执行顺序

当执行new Promise时👉构造函数(1.保存了一些状态信息 ,2.执行传入的参数),在执行传入的回调函数时,会传入两个参数,resolve, reject, 它两都是函数。

resolve是成功时调用,反过来就有reject(拒绝)

  new Promise((resolve, reject) => {
    setTimeout(() => {
      //成功的时候调用
      resolve('我是promise')
    }, 1000)
  }).then((data) => {
    console.log(data);
  })

当代码执行到resolve()时,会执行then,并把参数传给thendata.

 new Promise((resolve, reject) => {
    setTimeout(() => {
      // 成功的时候调用
      // resolve('我是promise')
      //失败的时候调用
      reject('error message')
    }, 1000)
  }).then((data) => {
    console.log(data);
  }).catch(err => {
    console.log(err);
  })

reject时拒绝时执行,与resolve不同的是,它的下一步执行是到catch里去执行。同样可以把reject里的值传给err

Promise的另外一种写法

  <script>
    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('nih')
        reject('err')
      }, 1000)
    }).then(data => {
      // 函数一,相当于成功的时候调用
      console.log(data);
    }, err => {
      //函数二 ,相当于失败的时候调用
      console.log(err);
    })
  </script>

这种写法不同于上面的方法在于,then函数里放置了两个函数,一个是请求成功调用的,另一种是请求失败的时候调用的。

定时器的异步事件

嵌套变成变成链式编程,异步处理效率更高。

  • 嵌套编程
  setTimeout(() => {
    console.log('Hello World');
    console.log('Hello World');
    setTimeout(() => {
      console.log('Hello pink');
      console.log('Hello pink');
      setTimeout(() => {
        console.log('blue');
        console.log('blue');
      }, 1000)
    }, 1000)
  }, 1000)
  • 链式编程
  // 参数 ->函数(resolve,reject)
  new Promise((resolve, reject) => {
    //第一次网络请求的代码
    setTimeout(() => {
      resolve()
    }, 1000)
  }).then(() => {
    //第一次处理的代码
    console.log('Hello World');
    console.log('Hello World');

    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve()
      }, 1000);
    }).then(() => {
      console.log('Hello pink');
      console.log('Hello pink');

      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve()
        }, 1000)
      }).then(() => {
        console.log('blue');
        console.log('blue');
      })
    })
  })

肉眼可见的变成了链式,这只是用计时器模仿了一下异步请求的操作,重要的是promise的使用,以及体会到从嵌套到链式的转变

Promise三种状态

异步操纵后会有三种状态。

  • padding:等待状态,比如正在进行网络请求,或者定时器没有到时间。
  • fulfill :满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调 .then()
  • reject :拒绝状态,当我们主动回调了reject时,就处于该状态,并且会回调 .catch()

  1. 一个promise可能有三种状态:等待(pending)、已完成(fulfilled)、已拒绝(rejected)
  2. 一个promise的状态只可能从“等待”转到“完成”态或者“拒绝”态不能逆向转换,同时“完成”态和“拒绝”态不能相互转换
  3. promise必须实现then方法(可以说,then就是promise的核心),而且then必须返回一个promise,同一个promise的then可以调用多次,并且回调的执行顺序跟它们被定义时的顺序一致
  4. then方法接受两个参数,第一个参数是成功时的回调,在promise由“等待”态转换到“完成”态时调用另一个是失败时的回调,在promise由“等待”态转换到“拒绝”态时调用。同时,then可以接受另一个promise传入,也接受一个“类then”的对象或方法,即thenable对象。

Promise链式调用

  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('aaa')
    }, 1000)
  }).then(res => {
    console.log(res, '第一层的处理代码');
    //new Promise(resolve => resolve(结果))简写
    return Promise.resolve(res + '111')
    return Promise.reject('error message')
    //throw 'error message'
  }).then(res => {
    console.log(res, '第二层处理的代码');
    // 省略掉Promise.resolve
    return res + '222'
  }).then(res => {
    console.log(res, '第三层处理的代码');
    //最原生的写法
    return new Promise(resolve => {
      resolve(res + '333')
    })
  }).then(res=>{
    console.log(res, '第四层处理的代码');
  })

注意观察Promise只在第一步进行了异步,同时注意promise三种书写方式,同时抛出错误信息不但可以使用Promise.reject('error'),还可以通过throw 'error'来抛出异常。

Promise的all方法

适用情况:需求依赖两个或者多个请求才可以完成。

  Promise.all([
    new Promise((resolve, reject) => {
      $ajax({
        url: 'url1',
        success: function (data) {
          console.log(data);
        }
      })
    }),
    new Promise((resolve, reject) => {
      $ajax({
        url: 'url2',
        success: function (data) {
          console.log(data);
        }
      })
    })
  ]).then(results => {
    results[0]
    results[1]
  })
  Promise.all([
    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({ name: 'liyu', age: 18 })
      }, 1000)
    }),
    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({ name: 'kobe', age: 19 })
      }, 2000)
    })
  ]).then(results => {
    console.log(results);
  })

适用promise方法对两次请求进行封装,最终结果会保存到results的结果数组中,下标为0返回的是第一个结果,下标为1返回第二个结果。

Snipaste_2022-06-22_23-25-08

posted @ 2022-07-16 08:11  抗争的小青年  阅读(57)  评论(0编辑  收藏  举报