Powerful $http in AngularJS

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 裡面,不知道 taskAtaskB 究竟裡面做了什麼事的情況下,就會發生重覆對 api/commonGET request 的情況。

你說不是有加 {cache: true} 嗎? 但一般來說 cache 可以作用的前提是東西已經拿到了。在上面的範例裡,taskB 執行的時候有非常高的可能性 taskA 裡面的 request 還未完成,也就是說 cache 還是空的,於是就會在前一個 request 未完成的情況下再發一個一模一樣的 request。

範例: http://plnkr.co/edit/sXZYgC?p=preview

打開開發者工具來確認一下 XHR 的情況...

竟然只有一個 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 寫法太特殊了嗎...

ParrotTalks抄筆記 持續推廣中!

comments powered by Disqus