1. 程式人生 > >Fly攔截全域性Ajax請求

Fly攔截全域性Ajax請求

大多數情況下,我們的 Ajax 請求都是通過前端的開發庫、框架發出的,如 jQuery、axios 或者 Fly。這些庫自身都會有一些請求/響應鉤子,用於預處理 Ajax請求和響應。但是,如果你沒有使用這些網路庫,又或是你並不是網頁的開發者,而你需要分析某個網頁的所有Ajax請求,又或是你是一個應用開發者,你的webview中需要攔截所有網頁的網路請求(網頁並不是你開發的)…… 這種時候,你就需要攔截全域性的 Ajax 請求.

原理

無論你的應用是通過那個框架或庫發起的 Ajax 請求,最終都會迴歸到 XMLHttpRequest 。 所以,攔截的本質就是替換瀏覽器原生的 XMLHttpRequest

。具體就是,在替換之前儲存先儲存 XMLHttpRequest,然後在請求過程中根據具體業務邏輯決定是否需要發起網路請求,如果需要,再建立真正的 XMLHttpRequest 例項。

Fly 攔截全域性ajax

我們知道,在 Fly 中,XMLHttpRequest 就是一個 http engine。所以我們要攔截,只需要自定義一個engine替換掉全域性的XMLHttpRequest 就行,而 Fly 提供了快速生成 engine 的工具,所以我們可以很方便實現攔截。

我們先看一個簡單的例子,功能是輸出每次網路請求 url 和 method。

實現

 var log = console.log;
//切換fly engine為真正的XMLHttpRequest
fly.engine = XMLHttpRequest; var engine = EngineWrapper(function (request, responseCallback) { console.log(request.url, request.method) //發起真正的ajax請求 fly.request(request.url, request.data, request) .then(function (d) { responseCallback({ statusCode: d.engine.status, responseText: d.engine.responseText, statusMessage: d.engine.statusText }) }) .catch(function
(err) {
responseCallback({ statusCode:err.status, statusMessage:err.message }) }) }) //覆蓋預設 XMLHttpRequest = engine; axios.post("../package.json").then(log)

我們用 axios 發起一個請求測試一下:

axios.post("../package.json").then(log)

//控制檯輸出
> http://localhost:63341/Fly/package.json POST
> {data: {…}, status: 200, statusText: "OK", headers: {…}, config: {…}, …}

可以看到控制檯中輸出了請求的 url 和 method,我們的攔截成功了。而 第二行的結果物件是axios then打印出的。

因為 Fly支援切換engine, 我們可以直接先將 fly engine 切換為真正的 XMLHttpRequest ,然後再覆蓋,這樣fly中的網路請求都是通過真正的 XMLHttpRequest 發起的 (事實上, 瀏覽器環境下 fly 預設的 engine本就是 XMLHttpRequest,無需手動切換,此處為了清晰,故手動切換了一下)。fly 會根據request物件自動同步請求頭。如果想阻止請求,直接在 adapter 中 return 即可。

其它攔截方法

Github上的開源庫 Ajax-hook 也可以攔截全域性的的ajax請求,不同的是,它可以攔截ajax請求的每一步,每一個回撥,不僅強大,而且也很輕量(1KB)。和上面通過 fly engine 攔截的方式相比 ,Ajax-hook的攔截粒度更細,但Ajax-hook由於使用了ES5的 gettersetter,所以不支援IE9以下的瀏覽器。

最後