ES6学习笔记(一)——Promise

Promise 是 ES6 提供的一种异步编程的解决方案: 将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数(解决异步函数回调地狱的问题)。
Promise 对象保存着异步操作的结果。

首先看异步的概念,这在《ECMAScript6入门》中介绍的很好:

所谓"异步",简单说就是一个任务不是连续完成的,可以理解成该任务被人为分成两段,先执行第一段,然后转而执行其他任务,等做好了准备,再回过头执行第二段。

比如,有一个任务是读取文件进行处理,任务的第一段是向操作系统发出请求,要求读取文件。然后,程序执行其他任务,等到操作系统返回文件,再接着执行任务的第二段(处理文件)。这种不连续的执行,就叫做异步。

相应地,连续的执行就叫做同步。由于是连续执行,不能插入其他任务,所以操作系统从硬盘读取文件的这段时间,程序只能干等着。

而JS对异步编程的实现就是通过回调函数(把任务的第二段单独写在一个函数里面,等到重新执行这个任务的时候,就直接调用这个函数),回调函数本身并没有问题,问题就在于嵌套的形式容易因为层次太深而变得混乱难以维护(多个异步操作形成了强耦合,只要一个曹组哦需要修改,它的上层和下层回调函数都要跟着修改),因此为了解决这个问题,Promise 采用了新链式写法,使得任务不同的执行阶段变得清晰。

Promise 特点:
1. 其状态不受外界影响:
 Pending: 进行中
 Fulfilled: 已成功
 Rejected: 已失败
2. 状态一旦改变便不会再变。
 Pending -> Fulfilled: Resolved => then(res => {...})
 Pending -> Rejected: Rejected => catch(err => {...})

创建一个 Promise 实例

var promise = new Promise((resolve, reject) => {
  if (success) {
    resolve(value)
  } else {
    reject(error)
  }
})
promise.then(value => {...}, error => {...})

Promise 新建后就会立即执行

resolved 的 Promise 是在本轮事件循环的末尾执行,总是晚于本轮循环的同步任务。

调用resolve或reject以后,Promise 的使命就完成了,后继操作应该放到then方法里面,而不应该直接写在resolve或reject的后面。所以,最好在它们前面加上return语句,这样就不会有意外。

new Promise((resolve, reject) => {
  return resolve(1);
  // 后面的语句不会执行
  console.log(2);
})

Promise.prototype.then()

为 Promise 实例添加状态改变时的回调函数。then 方法的第一个参数是 Resolved 状态的回调函数,第二个参数(可选)是 Rejected 状态的回调函数(更多的是直接写成 catch 方法)。
then方法返回的是一个新的 Promise 实例(注意,不是原来那个 Promise 实例)。因此可以采用链式写法,即 then 方法后面再调用另一个 then 方法。

getJSON("/posts.json").then(function(json) {
  return json.post;
}).then(function(post) {
  // ...
});

promise 中的 then 和 catch 方法可以交换位置,但是执行顺序也会被交换,如果在 then 方法中报错,在前面的 catch 中就无法捕获了。
catch 中可以继续抛出错误,因此 catch 后面可以继续写 catch 方法来捕获错误。

Promise.all()

var p = Promise.all([p1, p2, p3])

p1, p2, p3 都是 Promise 实例,只有这些实例的状态都变成 fulfilled ,p 的状态才会变成 fulfilled,否则只要有一个实例的状态变成 rejected,这个实例被 rejected 返回的值就会传递给 p

done()

Promise 对象的回调链,最后一个方法(then 或 catch)抛出的错误都无法被捕获,因此可以在回调链末尾使用 done 方法来处理抛出的错误。

asyncFunc()
  .then(f1)
  .catch(r1)
  .then(f2)
  .done();

finally()

用于指定不管 Promise 对象最后状态如何都会执行的操作。

server.listen(0)
  .then(function () {
    // run test
  })
  .finally(server.stop);

参考:http://es6.ruanyifeng.com/#docs/promise

 

posted @ 2017-08-30 17:53  Raychan  阅读(215)  评论(0编辑  收藏  举报