卡通方式趣解 AngularJS 中的 promise
2013-12-17 13:01 阅读(178)

本文由 伯乐在线 - 蔡蔡 翻译自 Andy Shora

一天早晨,爹对儿子说:“宝儿,出去看看天气如何!”

每个星期天的早晨,爹都叫小宝拿着超级望远镜去家附近最高的山头上看看天气走势如何,小宝说没问题,我们可以认为小宝在离开家的时候给了他爹一个promise。

这时候,他爹就想了,如果明天艳阳高照,他就准备去钓鱼,如果天实在不行,就作罢,如果小宝对预报明天的天气也没底,他就在家宅一天哪也不去。

大概过了半小时,小宝回来了。每周的结果不尽相同:

A计划 :天气晴朗

小宝不辱使命,说外面阳光明媚,万里无云,这个promise was resolved(小宝信守承诺),爹就可以收拾行装,钓鱼去鸟。


B计划: 小宝日观天象,阴转小雨的节奏

小宝依然不辱使命,但是天公不作美,promise was resolved,但是孩儿他爹觉得还是搁家呆着吧。


C计划:天象诡谲,小宝无法做出天气走势判断

小宝败兴而归,云雾重重,遮蔽了视线,不敢妄言天气走势,小宝走的时候立下承诺说要给他爹预报天气,但是没有成功,我们说promise was rejected!孩儿他爹决定小心驶得万年船,还是在家吧。


上述种种,用代码写出来是什么样子呢?

我们可以把孩儿他爹看成controller,小宝就是service。

整理逻辑:孩儿他爹让小宝去看天气,小宝不能立刻告诉他,但是孩儿他爹在等待结果的这段时间里可以抽抽烟,喝喝茶啥的,因为小宝承诺会把天气情况搞清楚。等小宝把天气预报带回来,他就可以决定下一步干啥。各位看官注意了:小宝登高望远看天气的时候并没有影响他爹干别的事情,这就是promise的妙处所在。

Angular里有个then()函数,我们可以决定孩儿他爹到底是用哪个计划(ABC)then()接收两个functions作为参数,第一个在promise is resolved的时候执行,另一个在promise is rejected的时候执行

Controller: FatherCtrl 

孩儿他爹掌控局面的代码如下:

// function somewhere in father-controller.js
       var makePromiseWithSon = function() {
           // This service's function returns a promise, but we'll deal with that shortly
           SonService.getWeather()
               // then() called when son gets back
               .then(function(data) {
                   // promise fulfilled
                   if (data.forecast==='good') {
                       prepareFishingTrip();
                   } else {
                       prepareSundayRoastDinner();
                   }
               }, function(error) {
                   // promise rejected, could log the error with: console.log('error', error);
                   prepareSundayRoastDinner();
               });
       };


Service: SonService

小宝的作用就是充当了一个service,他爬上山头看天象,有点类似调用weather API而且还是异步调用,他得到的结果可能是个变量,也有可能出现异常情况(比如,返回500—>大雾弥漫)。

从”Fishing Weather API”返回一个promise,如果it was resolved就格式化成{“forecase”:”good”}。

app.factory('SonService', function ($http, $q) {
        return {
            getWeather: function() {
                // the $http API is based on the deferred/promise APIs exposed by the $q service
                // so it returns a promise for us by default
                return $http.get('http://fishing-weather-api.com/sunday/afternoon')
                    .then(function(response) {
                        if (typeof response.data === 'object') {
                            return response.data;
                        } else {
                            // invalid response
                            return $q.reject(response.data);
                        }
 
                    }, function(response) {
                        // something went wrong
                        return $q.reject(response.data);
                    });
            }
        };
    });


总结

这个比喻向我们展示了异步的实质,孩儿他爹不会倚门等待儿子的归来,这段时间他完全可以自由活动。 孩儿他爹到底用哪个计划取决于(天气好/坏,没有成功预报),小宝在临走的时候给他爹一个promise,就等他回来的时候决定是resolve还是reject。

小宝其实是在使用异步服务(观天象—调用weather API)来获取天气信息,孩儿他爹根本就不懂技术,坐等结果即可!