14-Promise

1、Promise

Promise 是 ES6 中一个非常重要和好用的特性,是异步编程的一种解决方案;


通常在网络请求时,我们会处理异步事件,因为不能立即拿到结果,所以往往会传入另外一个函数,在数据请求成功时,将数据通过传入的函数回调出去;


如果只是一个简单的网络请求,那么这种方案不会给我们带来很大的麻烦,但当网络请求非常复杂时,就会出现回调地狱;


2、网络请求的回调地狱

我们来考虑下面的场景:

  • 通过一个 url1 从服务器加载一个数据 data1,data1 中包含了下一个请求的 url2
  • 再通过 data1 取出 url2,从服务器加载数据 data2,data2 中包含了下一个请求的 url3
  • 再通过 data2 取出 url3,从服务器加载数据 data3,data3 中包含了下一个请求的 url4
  • 最后发送网络请求 url4,获取最终的数据 data4


图片.png


正常情况下,上面的代码不会有什么问题,可以正常运行,并且获取我们想要的结果;


但是,这样的代码难看而且不容易维护;


我们期望的是以一种更加优雅的方式来进行这种异步操作:使用 Promise


3、定时器的异步事件

用一个定时器来模拟异步事件:

图片.png


假设下面的 data 是从网络上 1 秒后请求的数据,console.log 就是我们的处理方式,


这是过去的处理方式,我们将它换成 Promise 代码:

图片.png


这个例子会让我们感觉使用 Promise 有些多此一举,因为下面的 Promise 代码明显比上面的代码看起来还要复杂;


定时器异步事件解析

我们先来认认真真的读一读这个程序到底做了什么?

  • new Promise 创建了一个 Promise 对象
  • 小括号中 ((resolve, reject) => {}) 是一个箭头函数
    • 在创建 Promise 时,传入的这个箭头函数是固定的(一般我们都会这样写)
    • resolve 和 reject 也是函数,通常情况下,会根据请求数据的成功和失败来决定调用哪一个
      • 如果是成功的,通常会调用 resolve(messsage),这时,后续的 then 会被回调
      • 如果是失败的,通常会调用 reject(error),这时,后续的 catch 会被回调


4、promise 的三种状态

当开发中有异步操作时,可以给异步操作包装一个 Promise,异步操作之后会有三种状态:

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

图片.png


以上代码的另一种写法:

图片.png


5、Primose的链式调用

<script>
  // promise 链式调用
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Hello World')
    }, 1000)
  }).then(data => {
    console.log(data) // Hello World
    return Promise.resolve(data + '111')
  }).then(data => {
    console.log(data) // Hello World111
    return Promise.resolve(data + '222')
  }).then(data => {
    console.log(data) // Hello World111222
    return Promise.reject(data + 'error')
  }).then(data => {
    console.log(data) // 这里代码不会执行,没有输出
    return Promise.resolve(data + '333')
  }).catch(data => {
    console.log(data) // Hello World111222error
    return Promise.resolve(data + '444')
  }).then(data => {
    console.log(data) // Hello World111222error444
  })
</script>


链式调用简写

将数据直接包装成 Promise.resolve,在 then 中直接返回:

<script>
  // promise 链式调用简写
 new Promise((resolve, reject) => {
  setTimeout(() => {
        resolve('Hello World')
      }, 1000)
  }).then(data => {
    console.log(data) // Hello World
    return data + '111'
  }).then(data => {
    console.log(data) // Hello World111
    return data + '222'
  }).then(data => {
    console.log(data) // Hello World111222
    return Promise.reject(data + 'error')
  }).then(data => {
    console.log(data) // 这里代码不会执行,没有输出
    return data + '333'
  }).catch(data => {
    console.log(data) // Hello World111222error
    return data + '444'
  }).then(data => {
    console.log(data) // Hello World111222error444
  })
</script>


6、promise的all方法的使用

<script>
  // Promise 的 all 方法使用
  Promise.all([
    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({
          name: 'lyy',
          age: 18
        })
      }, 1000)
    }),
    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({
          name: 'sss',
          age: 17
        })
      }, 2000)
    })
  ]).then(results => {
    console.log(results);
  })
</script>


原文地址:https://www.cnblogs.com/weiyiming007/p/13729908.html