由于JavaScript的语言特性:

  • 单线程(single threaded)
  • 同步执行(Synchronously executed)

但在有的时候需要JavaScript进行异步执行代码,ES6给出的解决方法是Promise。

Promise的基本介绍:

promise翻译成中文有‘承诺’的意思,意思给你一个承诺,后期可能会实现承诺也可能会没用实现承诺。

promise有三种状态:

  • 待定( pending ) : 初始状态,既没有被兑现,也没有被拒绝
  • 已实现( resolve / fulfilled ) : 意味着操作已经完成
  • 已拒绝 (rejected):意味着操作失败

promise

从图中我们可以清楚的看出 promise 三种状态之间的关系:

  • 成功 ( reslove ) ⇒ 调用resolve , 会执行Promise对象的then方法传入回调函数

  • 失败 ( rejected ) ⇒ 调用reject , 会执行Promise对象的catch方法传入回调函数

Promise 的状态一旦被确定下来,无法被更改,resolve、reject两个函数不会代码禁止向下执行,为了防止继续向下执行,所以要加上return。

Promise的then/catch方法:

promise 中有then()方法,返回一个 promise。接受两个参数:Promise 的成功(reslove)和失败(reject)情况的回调函数。

const p = new Promise()
p.then(data => {
  // resolve dosomething
}, err => {
  // reject dosomething
});

也可以写作:

promise.((resolve, reject)=>{
    // resolve(data) 或者 reject(err)
    // dosomething
})

又由于then和catch方法都会返回 promise,所以 promise 可以被链式调用

链式调用

Promise 实现了链式调用,也就是说每次调用 then 之后返回的都是一个 Promise,并且是一个全新的 Promise,原因也是因为状态不可变。如果你在 then 中 使用了 return,那么 return 的值会被 Promise.resolve()或者Promise.reject() 包装

Promise.resolve(1)
  .then(res => {
    console.log(res) // => 1
    return 2 // 包装成 Promise.resolve(2)
  })
  .then(res => {
    console.log(res) // => 2
  })

举一个小例子

function foo(url) {
  return new Promise((resolve, reject) => {
    // 假设这是网络请求,需要请求完毕才能返回给用户使用
    setTimeout(() => {
      if (url === 'success') {
        resolve({ code: '200', message: '请求成功' })
      } 
      if (url === 'failure') {
        reject({ code: '-200', message: '请求失败' })
      }
    }, 1000)
  }).then(data => {
    console.log(data);
  }).catch(err => {
    console.log(err);
  })
}
foo('success')
foo('failure')

当foo()函数传入的是success值时,pedding状态转化为fullfill,会调用resolve执行Promise对象的then方法传入回调函数,最后打印出{ code: '200', message: '请求成功' }

当foo()函数传入的是failure值时,pedding状态转化为reject,会调用resolve执行Promise对象的catch方法传入回调函数,最后打印出{ code: '-200', message: '请求失败' }

Reference

  1. 前端基础进阶(十三):透彻掌握Promise的使用,读这篇就够了 - SegmentFault 思否