Angular 的 $q 这个服务,可以帮助我们在应用里使用异步功能。跟异步对应的就是同步,用一个现实生活的例子来理解一下他们之间的区别。
比如我要通知小雪,中午不回家吃饭了,我可以给小雪打个电话,或者发个短信。打电话就像是同步的功能,拔打小雪的电话,我得一直得到小雪接通了电话,然后告诉她我中午不回家吃饭了,在这个过程中,我不能去做其它的事情。得等着 ...
发短信就像是一个异步功能,我发了个短信,告诉小雪中午不回家吃饭了,然后我就可以去干别的事情了,比如到商场买两包纸尿裤什么的 ... 一会儿小雪收到短信,然后给我回了个信息,我看到了信息,再决定下一步要做的事,比如小雪回复,不行 ... 那我就得回家吃饭,如果回复,ok ... 我就决定继续待在外面。
$q 这个服务用到了 deferred/promise .. 理解什么是 deferred / promise ,我们可以先看一个故事 ... Andy Shora 用卡通的形式解释了什么是 promise ...
一个关于 promise 的故事:爸爸跟儿子
http://andyshora.com/promises-angularjs-explained-as-cartoon.html
-------
星期天一早,爸爸让儿子帮着上网查查今天的天气,他决定,如果天气好的话,就出去钓鱼,天气不好的话,就待在家里准备晚上烧烤 ... 还有一种可能,就是儿子没法查到天气,家里可能装的是铁通宽带,经常掉线,如果是这样的话,爸爸也决定待在家里 ...
儿子收到了爸爸的请求,答应爸爸会给他带回天气的情况 ... 在儿子查天气这期间,爸爸可以继续去做他的事情 ... 一会儿,儿子如果能兑现他的承诺,带着天气情况回来找爸爸,爸爸就会根据事先规划好的,天气好就去钓鱼,天气不就待在家里 ...
--------
代码
在这个故事里,爸爸就像是一个 Controller 控制器,儿子像是一个 Service 服务 ...
下面我们再看一下这个小故事转换成代码的话大概是什么样子的 ...
这是一个可能包含在控制器里的函数,比如 FartherController ... 爸爸控制器 ... 在这个函数里,用到了一个 SonService ... 儿子服务 ... 用了他的 getWeather() 这个方法去获取天气的情况 ... 然后用了一个 then ... 这个方法有两个参数,第一个是儿子兑现了承诺以后要执行的函数 ... 这个函数上有个叫 data 的参数,儿子如果成功得到了天气情况,这个天气情况就是这里的 data ... 在这个函数里面,判断了天气情况 ... 如果是 good ... 就执行 prepareFishingTrip() 准备去钓鱼 ... 如果是其它的天气情况,就执行 prepareSundayRoastDinner() ... 去准备晚餐 ...
.then 的第二个参数是不能兑现承诺以后要执行的函数 ... 这里也去执行 prepareSundayRoastDinner() ...
再看一下 SonService ... 儿子服务 ...
这个服务里面有一个 getWeather 方法 ... 就是 FartherController 用到的这个方法 ... 在这个方法里面,用到了一个叫 $http 的服务 ... 它可以发送 http 请求,这里用的是 $http 的 get 方法 ... 这个方法可以去到指定的地方获取到数据 ...
$http 这个服务用到了 $q 服务 ... 所以它会返回一个 promise ,也就是承诺 ... 接着用了 .then .. 也就是如果上面的 get 方法成功得到了数据,就会去执行这个 then 方法里面的第一个参数的函数 ... 如果出现错误的话 ... 就会执行 .then 里面的第二个参数的函数 ...
成功得到天气情况要做的事这里,判断了一下用 get 方法返回来的数据的 data 属性,如果是 object 的话,就履行承诺,返回响应回来的数据 ...
如果不是,就返回一个 $q.reject ... 意思就是拒绝承诺,这样会去执行 .then 里的第二个参数的函数 .... 同样这个函数里面,也用到了 $q.reject ...