hiccLoghicc log by wccHipo日志

[译]用漫画来解说AngularJs中的Promises

toc

Intro

早上,父亲对儿子说:“儿子,去给我预报下天气!”

每一个晴天,父亲都会让他儿子带上他强劲的望远镜,爬山房子附近最高的山顶去查看地平线来预报下午的天气。儿子对他的父亲承诺他会去并且获取到天气预报,在他离开之前他对他的父亲做出了承诺。

在那个时候,父亲会判断明天是否是个好天气,他要准备明日的钓鱼。如果天气不好,他就不会去钓鱼,同时,如果他的儿子没能得到天气预报,他同样会呆在家里。

30分钟之后,他儿子回来了。不同的事情周而复始的发生着:

结果A) 得到了天气预报!晴天:-)

儿子成功的拿到了天气预报,蓝蓝的天空是个晴天!承诺履行了(儿子遵守了他的诺言),父亲决定周日去钓鱼。

promise 1

结果B) 得到了天气预报!乌云密布,有雨:-(

儿子成功的拿到了天气预报,但是看起来乌云密布要下雨!承诺履行了,父亲因为坏天气决定呆在家里。

promise 2

结果C) 没能拿到天气预报:-/

儿子没能拿到天气预报,遇到了点麻烦;雾太大了在山上看不到天气怎么样。儿子离家前做出的承诺没能遵守!父亲决定呆在家,不值得冒险。

promise 3

这如何在代码中表达?

在这种场景中父亲控制着逻辑,父亲把儿子作为一种服务来对待。

我们已经陈述了逻辑。父亲让儿子去获取天气预报,儿子没法立即告诉他,父亲在他等待的过程中还有些其他事情处理,等他儿子实现了承诺,父亲再回来处理天气的问题。当父亲拿到了天气预报,他或者准备去钓鱼,或者选择留在家里。在此值得一提的是,在他儿子爬山的时候不应该「锁定」父亲不让他做其他事情,这也就是为什么这种场景下许一个承诺,在之后决定(完成或者不完成)是个完美的方案。

使用AngularJs的then()函数我们可以指定每次父亲得到结果之后需要做什么。then()函数接受2个函数作为参数:一个用来在承诺完成时候执行,另一个用来在承诺未完成时候执行。

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),他爬上山去查看天气。我们将儿子通过望远镜查看天气,类比于通过天气API查询,在某种意义上这是一个异步的过程,他可能会得到不确定的结果,更甚者遇到难题(譬如,返回一个500,大雾天气)。

『完成天气API查询』将会返回一个承诺,如果完成了。它将会是这样的格式:{ "forecast": "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);
            	});
        }
    };
});

总结

这个类比的demo中父亲要求儿子去获取天气预报的本质是异步的,父亲不必干等者儿子回来,因为他还有其他事情做。相反,父亲通过一个承诺来决定之后三个可能发生(好天气/坏天气/没天气预报)中的一个。儿子在离开前立即给父亲一个承诺,并在他回来时候解决或者拒绝

儿子作为一个异步服务(通过望远镜查看天气/使用天气API)来获取数据,但是所有这些都出自他的父亲,谁又真正不懂技术呢?

原文:Promises in AngularJS, Explained as a Cartoon