2014-06-23 103 views
18

比方說,有人在一個文件中寫了一個方法,像這樣叫app.js試圖[執行angainst一個不存在的URL的XHR請求:

app.controller('MainCtrl', function($scope,$http) { 
    $scope.send = function() { 
    $http.get('http://run.plnkr.co/thisIs404'); 
    }; 
}); 

我可以看到一個錯誤在控制檯和網絡面板關於URL http://run.plnkr.co/thisis404

error in console

要調試此我要趕緊找到這個地方XHR呼叫的源發(即找到app.js文件):

所以我能夠在Chrome瀏覽器開發工具:在調用堆棧

  • 異步調試
  • 調試任何XHR

調試器實際上是停在XHR請求,但調用堆棧只顯示到引用angular.js「核心」文件:不參考app.js任何地方都可以找到

google chrome call stack

我試圖與鉻36,鉻35只解決方案:搜索整個代碼庫的網址有誤(在某些情況下,可能很難做到)。

  • 是不是異步調試模式應該指向app.js somwhere在堆棧?
  • 有沒有辦法從控制檯錯誤輕鬆跟蹤這個app.js文件?

香草XHR請求(即,沒有角),XHR調試調用堆棧顯示app.js的XHR呼叫(這是更容易調試在這種情況下):

enter image description here

完整的示例這裏: http://plnkr.co/edit/lnCRpv?p=preview

[編輯] 正如我問:Angular.js沒有在我的測試中縮小。

回答

10

所以,你看,這個問題主要是因爲角的$ http很糟糕。對於那個很抱歉。

讓我們嘗試使用藍鳥庫,因爲它提供了很長的堆棧跟蹤。

Promise.longStackTraces(); 
Promise.resolve($http.get('...')); 

會得到以下堆棧跟蹤:(Plunker here

Possibly unhandled Error: [object Object] 
    at Promise$_rejectFromThenable (http://cdn.jsdelivr.net/bluebird/1.2.4/bluebird.js:4736:52) 
    at wrappedErrback (https://code.angularjs.org/1.3.0-beta.5/angular.js:11334:78) 
    at wrappedErrback (https://code.angularjs.org/1.3.0-beta.5/angular.js:11334:78) 
    at wrappedErrback (https://code.angularjs.org/1.3.0-beta.5/angular.js:11334:78) 
    at https://code.angularjs.org/1.3.0-beta.5/angular.js:11467:76 
    at Scope.$eval (https://code.angularjs.org/1.3.0-beta.5/angular.js:12418:28) 
    at Scope.$digest (https://code.angularjs.org/1.3.0-beta.5/angular.js:12230:31) 
    at Scope.$apply (https://code.angularjs.org/1.3.0-beta.5/angular.js:12522:24) 
    at done (https://code.angularjs.org/1.3.0-beta.5/angular.js:8207:45) 
    at completeRequest (https://code.angularjs.org/1.3.0-beta.5/angular.js:8412:7) 

最重要的線是第一條:Possibly unhandled Error: [object Object]

是的。拋出一個對象,而不是一個真實的Error對象,並附加stack屬性。對於參考,這裏是如何拋出一個錯誤,並保持它的堆棧隨着它:https://github.com/Ralt/newerror/blob/master/index.js

那麼,如何解決這個問題?這取決於幾個決定:

  • 是否要添加一個適當的Promise庫來啓用長堆棧跟蹤?
  • 你想使用另一個引發正確錯誤的xhr庫嗎?

如果您想要添加一個真正的Promise庫,請使用bluebird。 AFAIK,它是少數提供長堆棧軌跡的軟件之一,也是最快的一個。

對於一個適當的xhr庫引發真正的錯誤,恐怕你在那裏運氣不好。編寫一個支持所需瀏覽器的自定義程序並不是很難。由於沒有IE8的支持,這個廠(藍鳥):

function xhr(url) { 
    return new Promise(function(resolve, reject) { 
     var xhr = new XMLHttpRequest(); 
     xhr.onload = function() { 
      resolve(xhr.responseText); 
     }; 
     xhr.onerror = reject; 
     xhr.open('GET', url); 
     xhr.send(); 
    }); 
} 

Plunker here。)

正如你所看到的,堆棧跟蹤信息:

correct stack trace

+2

是的,這個答案是正確的 - 這是因爲青鳥做未處理的排斥跟蹤和角度不 - 見[**這個問題**](HTTP:/ /stackoverflow.com/questions/23984471/how-do-i-use-bluebird-with-angular)如何使用藍鳥與AngularJS。 AngularJS承諾有非常糟糕的堆棧跟蹤,這使得在真實世界的場景中與他們合作非常困難。 –

+0

我們是否可以修改角色的http功能以使用藍鳥,以便它可以在沒有修改現有項目的情況下工作?那麼下面的內容:http://plnkr.co/edit/1boCEqUjSLx8zGX2uqSo – David

1

XHR請求堆疊在$http.pendingRequests數組中,並在稍後發送。這就是爲什麼你不能在調用$http的地方和實際的XHR請求的位置之間找到直接聯繫。

如果您想知道$http哪個函數,您必須在$http函數中設置斷點。

它在我看來打敗了整個「XHR斷點」的目的。

0

一個選項我想到的是爲$ http調試創建一個模塊,您可以在需要調試$ http調用時將其添加爲主模塊中的依賴項。有一個$ http服務的裝飾器可以被註冊,它將簡單地記錄調用的參數並將其轉發給$ http服務。有一個斷點也可以設置。

我已經創建了一個簡單的工作示例here。我希望這會有所幫助。

例子$ HTTP記錄器裝飾實現:

var httpDebugging = angular.module('http-debugging', []); 

httpDebugging.decorator('$http', function ($delegate) { 
    var debugAware = function (fnCallback) { 
    return function() { 
     var result = fnCallback.apply(this, arguments);  
     console.log('$http decorator: ', arguments); 
     return result; 
    }; 
    }; 

    for(var prop in $delegate) { 
    if (angular.isFunction($delegate[prop])) { 
     $delegate[prop] = debugAware($delegate[prop]); 
    } 
    } 

    return $delegate; 
}); 
+0

嗨,這給$ http調用的信息,這是有幫助的,但放置在$ http函數斷點達到相同。是否有可能提取調用者(最好是線路號,啓動了$ http請求? – David

+0

是的,請在console.log()語句中添加一個斷點,您可以看到調用的起始位置爲函數的第一個函數javascript調用堆棧。 –

+0

太棒了。我會更新它包括使用http://www.stacktracejs.com/ – David