对Promise的理解

90 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第10天,点击查看活动详情

前言

在ES6中有一个非常好用且重要的特性Promise,什么是Promise,Promise是用来做什么的?Promise其实是在js里异步编程的一种解决办法

那我们什么时候会用Promise处理异步事件呢?一种很常见的场景就是网络请求,当我们封装了一个网络请求,不能立即拿到结果,往往我们会传到另一个函数,在数据请求成功的时候,将数据通过传入的函数回调出去,当网络请求非常复杂的时候就会出现回调地狱

回调地狱

例如当我们通过ajax请求一个地址,成功之后继续进行另一个ajax请求,成功之后再继续进行下一个ajax请求直到最后一个请求结束,这就是回调地狱,这样的代码写起来复杂,不容易维护,而Promise可以以一种非常优雅的方式来解决这个问题

$.ajax({
  url,
  type:'GET',
  success:function(res){
    $.ajax({
      url,
      type:'GET',
      success:function(res){
        $.ajax({
          url,
          type:'GET',
          success:function(res){
            $.ajax({
              url,
              type:'GET',
              success:function(res){
                console.log(res);
              }
            })
          }
        })
      }
    })
  }
})

Promise解决回调地狱

使用setTimeout模拟异步事件,log模拟返回的结果

setTimeout(() => {
    console.log('模拟异步事件');
}, 1000);

我们对异步操作进行封装,封装成Promise代码,Promise是一个类,通过这个类new一个对应的对象,在new Promise的时候要求传入一个函数,函数本身里面有两个参数,一个是resolve,另一个是reject

resolve是解决的意思,而reject是拒绝的意思,resolve和reject本身也是一个函数

将异步操作封装进Promise里,当异步操作完成后调用resolve(),就会在Promise的最外面执行一个叫then的方法,在里面返回结果。然后继续return一个new Promise,在里面继续执行异步操作,异步操作完成后调用resolve(),继续执行Promise的最外面的then方法,一直到结束

这样一来就清晰很多了,解决了回调地狱的问题,将嵌套的代码变成了链式编程

new Promise((resolve,reject)=>{
  //第一次网络请求
  setTimeout(() => {
    resolve()
  }, 1000);
}).then(()=>{
  //第一次拿到结果
  console.log('模拟异步事件1');
  return new Promise((resolve,reject)=>{
    //第二次网络请求
    setTimeout(() => {
      resolve()
    }, 1000);
  })
}).then(()=>{
  //第二次拿到结果
  console.log('模拟异步事件2');
  return new Promise((resolve,reject)=>{
    //第三次网络请求
    setTimeout(() => {
      resolve()
    }, 1000);
  })
}).then(()=>{
  //第三次拿到结果
  console.log('模拟异步事件3');
})

2.gif

Promise的三种状态

Promise在执行异步操作之后会有三种状态:

  • pending:等待状态
  • fulfill:满足状态,调用resolve时处于该状态并回调.then()
  • reject:拒绝状态,调用reject时处于该状态并回调.catch()

其实then的参数里是有两个函数的,第一个是满足状态状态下执行,第二个在拒绝状态下执行,调用resolve的时候就会打印data,调用reject的时候就会打印err

new Promise((resolve,reject)=>{
  setTimeout(() => {
    resolve('成功')
    reject('失败')
  }, 1000);
}).then(data=>{
  console.log('resolve',data);
},err=>{
  console.log('reject',err);
})

图片.png

图片.png