Promise简介

zhaoyizhu0 2014-11-10

初识 Promise
在上年的年末,我们工作室在学校接了一个项目,当时一小伙伴带起 NodeJS 的学习热潮,于是我们选择用 NodeJS 搭起了我们项目的后端。当时项目里引入了形形色色的模块,令我觉得眼花缭乱(当时我是这么觉得的),其中有一个 Promise 的模块让我最为深刻,当时我们用的是 Promise 的这个 bluebird 实现。

什么是 Promise
Promise 是一种让异步代码书写起来更优雅的模式,能够让异步操作代码像同步代码那样书写并且阅读,比如下面这个异步请求的例子:

   

loadImg('a.jpg', function() {
      loadImg('b.jpg', function() {
        loadImg('c.jpg', function() {
          console.log('all done!');
        });
      });
    });

使用 Promise 模式可转变为:

   

var loadImage = new Promise(function(img) {
        loadImg(img);
    });
    loadImage('a.jpg').then(function() {
        return loadImage('b.jpg');
    }).then(function () {
        return loadImage('c.jpg');
    }).then(function () {
        console.log('all done!');
    });

简而言之,就是可以把异步形式的代码转变成同步代码形式。摆脱回调地狱。like this↓
曾经有个小偷潜入某神秘机构,偷出机密代码的最后一页,打开一看。

                                       

});
                                    });
                                });
                            });
                        });
                    });
                });
            });
        });
    });

 
一种同步函数与异步函数联系和通信的方式
同步函数最重要的两个特征
 1. 能够返回值
 2. 能够抛出异常

这其实和高等数学中的复合函数(function composition)很像:你可以将一个函数的返回值作为参数传递给另一个函数,并且将另一个函数的返回值作为参数再传递给下一个函数……像一条“链”一样无限的这么做下去。更重要的是,如果当中的某一环节出现了异常,这个异常能够被抛出,传递出去直到被 catch 捕获。

而在传统的异步操作中不再会有返回值,也不再会抛出异常——或者你可以抛出,但是没有人可以及时捕获。这样的结果导致必须在异步操作的回调中再嵌套一系列的回调,以防止意外情况的发生。

而 Promise 模式恰好就是为这两个缺憾准备的,它能够实现函数的复合与异常的抛出(冒泡直到被捕获)。符合 Promise 模式的函数必须返回一个 promise,无论它是是 fulfilled 状态也好,还是 failed(rejected) 状态也好,我们都可以把它当做同步操作函数中的一个返回值:

  

$.get("/user/784533") // promise return
        .then(function parseHandler(info) {
        var userInfo = parseData(JSON.parse(info));
        return resolve(userInfo); // promise return
    })
    .then(getCreditInfo) // promise return
    .then(function successHandler(result) {
       console.log("User credit info: ", result);
    }, function errorHandler(error) {
       console.error("Error:", error);
    })

 这样以来函数复合便一目了然:

   

try {
        var info = $.get("/user/784533"); //Blocking
        var userInfo = parseData(JSON.parse(info));
    
        var resolveResult = parseData(userInfo);
        var creditInfo = getCreditInfo(resolveResult); //Blocking

        console.log("User credit info: ", result);
    } cacth(e) {
        console.error("Error:", error);
    }

 AngularJS 中的 Promise
前端调用后端 api 的时候有一些场合也需要同步代码实现(比如在某个用户的 profile 加载完成以前,不可以渲染"用户资料")。最近学习AngularJS,所以便介绍 Angular 中的 Promise。

在 Angular 中的 Promise 实现是 $q

   

function asyncGreet(name) {
      // perform some asynchronous operation, resolve or reject the promise when appropriate.
      return $q(function(resolve, reject) {
        setTimeout(function() {
          if (okToGreet(name)) {
            resolve('Hello, ' + name + '!');
          } else {
            reject('Greeting ' + name + ' is not allowed.');
          }
        }, 1000);
      });
    }

    var promise = asyncGreet('Robin Hood');
    promise.then(function(greeting) {
      alert('Success: ' + greeting);
    }, function(reason) {
      alert('Failed: ' + reason);
    });

 

最后……
鄙人才疏学浅,一点点经验,如有谬误,欢迎指正。

huangruichang

 参考阅读

 1. 【翻译】Promises/A+ 规范
 2. Promise/A 的误区以及实践
 3. AngularJS 文档

相关推荐