2016-08-20 115 views
2

我今天正在學習角度攔截器。我做了一些樣本來更好地理解這個概念。這裏是小樣本。角度攔截器如何工作?

var app = angular.module("myApp", []); 
 

 
app.factory("timestampMaker", [ 
 
    function() { 
 
    var timestampMaker = { 
 
     request: function(config) { 
 
     console.log(config); 
 
     config.requestTimestamp = new Date().getTime(); 
 
     return config; 
 
     }, 
 
     response: function(response) { 
 

 
     response.config.responseTimestamp = new Date().getTime(); 
 
     return response; 
 
     } 
 
    }; 
 
    return timestampMaker; 
 
    } 
 
]); 
 

 
app.config(['$httpProvider', 
 
    function($httpProvider) { 
 
    $httpProvider.interceptors.push('timestampMaker'); 
 
    } 
 
]); 
 

 
app.run(function($http) { 
 
    $http.get('https://api.github.com/users/naorye/repos').then(function(response) { 
 
    console.log(response); 
 
    var time = response.config.responseTimestamp - response.config.requestTimestamp; 
 
    console.log("The request took" + (time/1000) + "seconds") 
 
    }); 
 
});
<html ng-app="myApp"> 
 

 
<head> 
 
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 
</head> 
 

 
</html>

當我做console.log(config)請求函數裏面,這裏是控制檯上的輸出。 enter image description here

我沒有得到如何responseTimestamp出現在請求中的配置對象,其中作爲其響應函數中定義

回答

0

我使用的源代碼的1.2.x這是一個在的問題添加。

$httpProvider是一個爲您提供$http服務的提供商。

作爲一個提供者,在配置時暴露一個公共數組 - 你只需添加你想要注入到你的響應/請求中的所有服務名字的字符串。

這就是你在這裏做

app.config(['$httpProvider', 
    function($httpProvider) { 
    $httpProvider.interceptors.push('timestampMaker'); 
    } 
]); 

,它可以在配置時間只能做,因爲每docs提供商可以在應用程序之前配置的內容開始

你可以看到在暴露陣列source code在行159

var responseInterceptorFactories = this.responseInterceptors = []; 

當你請求$http服務,它注射到你的服務/控制器, $get函數被執行。在該功能,您的攔截器陣列迭代,因爲你可以在source code排隊見179

var reversedInterceptors = []; 
    forEach(responseInterceptorFactories, function(interceptorFactory, index) { 
     var responseFn = isString(interceptorFactory) ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory); 

     /** 
     * Response interceptors go before "around" interceptors (no real reason, just 
     * had to pick one.) But they are already reversed, so we can't use unshift, hence 
     * the splice. 
     */ 
     reversedInterceptors.splice(index, 0, { 
     response: function(response) { 
      return responseFn($q.when(response)); 
     }, 
     responseError: function(response) { 
      return responseFn($q.reject(response)); 
     } 
     }); 
    }); 

按照慣例,他們顛倒順序。您可以看到,使用字符串,他們使用$injector.get$injector.invoke獲得對該函數的引用,並且使用$q.when()我們可以將它們引入承諾鏈,即使它們是同步代碼 - 如果您不確定我的意思,請參閱此Can I use $q.all in AngularJS with a function that does not return a .promise?$q.when()

到目前爲止,我們有一個函數的數組,這些都是諾言般的(感謝$q.when())。當你請求的數據thorught $http這樣

$http.get('https://api.github.com/users/naorye/repos').then(function(response) { 
    console.log(response); 
    var time = response.config.responseTimestamp - response.config.requestTimestamp; 
    console.log("The request took" + (time/1000) + "seconds") 
    }); 

即使你有.get(),只是對所有相同功能的shorcut這是here

在代碼中的相關部分是這樣的一個:

首先用兩個值創建一個鏈式數組:一個內部函數對我們來說不是重要的(但它返回一個承諾 - 這很重要)和未定義的值。

我們使用攔截器的數組是迭代的,請求攔截器在開始時(請求之前)和響應結束處添加。像這樣

function serverRequest { 
     // some code 
    }; 
    var chain = [serverRequest, undefined]; 
    var promise = $q.when(config); 

    // apply interceptors 
    forEach(reversedInterceptors, function(interceptor) { 
     if (interceptor.request || interceptor.requestError) { 
     chain.unshift(interceptor.request, interceptor.requestError); 
     } 
     if (interceptor.response || interceptor.responseError) { 
     chain.push(interceptor.response, interceptor.responseError); 
     } 
    }); 

然後,具有鏈條完整的(記住我們的攔截器的陣列是充滿希望的),代碼迭代時,使用.then()將所有這些,使所有的人都在鏈執行,以下承諾鏈接(你可以谷歌認爲)

while(chain.length) { 
     var thenFn = chain.shift(); 
     var rejectFn = chain.shift(); 

     promise = promise.then(thenFn, rejectFn); 
    } 

最後,回調你success添加和error在鏈的最末端,並將該承諾返回

promise.success = function(fn) { 
    promise.then(function(response) { 
    fn(response.data, response.status, response.headers, config); 
    }); 
    return promise; 
}; 

promise.error = function(fn) { 
    promise.then(null, function(response) { 
    fn(response.data, response.status, response.headers, config); 
    }); 
    return promise; 
}; 

return promise; 

我不知道的只有部分是鏈陣列中使用的undefined

摘要

您爲您的服務添加姓名,$HttpProvider使用$invoke服務,讓他們,並增加了他們承諾鏈使用$q.when(),返回承諾。在那結束時,您添加了對特定$http請求的回撥