TL;DR
如果你怕 $http
會因為散布在各個 service 中而不小心送出多次同樣參數的 request,真的是白擔心了!
正文開始
今天本來心血來潮花了兩個小時想要做一個小 demo,來分享一下利用 promise 來避開在各個不同的 service 裡面對同一個 async task 套用一樣的參數而做重覆的 request 的問題。
不如直接看個上述情況最常碰到的 $http
範例。
angular.module('myApp', [])
.factory('common', function ($http) {
return function () {
return $http.get('api/common', {cache: true});
};
})
.factory('taskA', function (common) {
return function () {
return common()
.then(function () {
// Do something
return 'taskA';
});
};
})
.factory('taskB', function (common) {
return function () {
return common()
.then(function () {
// Do something
return 'taskB';
});
};
})
.controller('MainCtrl', function (taskA, taskB, $timeout) {
taskA();
$timeout(function () {
taskB();
}, 100);
});
在 MainCtrl
controller 裡面,不知道 taskA
及 taskB
究竟裡面做了什麼事的情況下,就會發生重覆對 api/common
做 GET
request 的情況。
你說不是有加 {cache: true}
嗎? 但一般來說 cache 可以作用的前提是東西已經拿到了。在上面的範例裡,taskB
執行的時候有非常高的可能性 taskA
裡面的 request 還未完成,也就是說 cache 還是空的,於是就會在前一個 request 未完成的情況下再發一個一模一樣的 request。
範例: http://plnkr.co/edit/sXZYgC?p=preview
竟然只有一個 request!!! 怎麼一回事!!!!???
Powerful $http
於是我就去爬了一下 angular 的 source code,發現他們早早就已經做了一些應對的措施…
https://github.com/angular/angular.js/blob/master/src/ng/http.js#L859
真是浪費了我兩個小時…
值得注意的是
只有在有設定
cache
的情況下,避免 XHR pending 時重覆 request 的機制才會起作用
拿掉 {cache: true}
的版本: http://plnkr.co/edit/1Lq2Ft?p=preview
後記
在接觸 AngularJS 一年之後才發現這個事實,果然是因為我們家網站的API service 寫法太特殊了嗎…