《深入理解ES6》阅读笔记 --- Promise与异步编程

《深入理解ES6》阅读笔记 --- Promise与异步编程

在异步编程概念已经普及的今天,我们依然要谈一谈它,对于我们做前端代码的意义。当你通过Ajax请求数据使用回调函数来获取数据时,这就是一种异步编程。

$.ajax({
  url: 'xxx',
  success: function(data){
    // data
  }
})

考虑到JavaScript属于单线程的特点,异步对于这门语言就可见多么的重要。你可以试着想想,当我们没有异步时,我正准备提交一个信息,界面就卡住了,一直要等待信息返回结果才能有接下来的其他操作,这很痛苦。在JavaScript的世界里,异步是非常重要的一件事情。

Promise正是想来处理这样的异步编程,如果我们用Promise该如何处理这段Ajax?

function fetch(){
  return new Promise(function(resolve,reject){
    $.ajax({
      url: 'xxx',
      success:function(data){
        resolve(data)
      },
      error:function(error){
        reject(error)
      }
    })
  })
}

fetch().then(function(data){

}).catch(function(error){})

这辅助我们避免了回调地狱式的恐惧,更优雅的处理了回调。如果,你有兴趣,可以配合着 Promise 来学习【理论上的内容,可以仔细阅读】。

Promise声明周期

  • 进行中(pending)
  • 已经完成(fulfilled)
  • 拒绝(rejected)

如同上面Ajax的例子,我们可以很好的包装一个函数,让fetch函数返回一个Promise对象。在Promise构造函数里,可以传入一个callback,并且在这里完成主体逻辑的编写。唯一需要注意的是:Promise对象只能通过resolve和reject函数来返回,在外部使用then或catch来获取。如果你直接抛出一个错误(throw new Error('error')),catch也是可以正确的捕获到的。

Promise其他的方法

  • Promise.all(当所有在可迭代参数中的 promises 已完成,或者第一个传递的 promise(指 reject)失败时,返回 promise。)
var p1 = Promise.resolve(3);
var p2 = 1337;
var p3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, "foo");
}); 

Promise.all([p1, p2, p3]).then(values => { 
  console.log(values); // [3, 1337, "foo"] 
});
  • Promise.race(返回一个新的 promise,参数iterable中只要有一个promise对象"完成(resolve)"或"失败(reject)",新的promise就会立刻"完成(resolve)"或者"失败(reject)",并获得之前那个promise对象的返回值或者错误原因。)
var p1 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 500, "one"); 
});
var p2 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 100, "two"); 
});

Promise.race([p1, p2]).then(function(value) {
  console.log(value); // "two"
  // 两个都完成,但 p2 更快
});

有趣的是如果你使用ES6的class,你是可以去派生Promise的,就像我们想派生Array一样:

class MePromise extends Promise{
 // 处理 ...
}

那么,除了Promise还有没有更牛逼的方案?这是有的,目前的异步编程已经从最初的callback进化到了如下的顺序。

callback -> Promise -> generator -> async await

未来,肯定属于async await了。

编辑于 2018-08-12

文章被以下专栏收录