让我们说有人在名为app.js
的文件中写了这样的方法,试图对一个不存在的网址执行XHR请求:
app.controller('MainCtrl', function($scope,$http) {
$scope.send = function() {
$http.get('http://run.plnkr.co/thisIs404');
};
});
我可以在控制台和网络面板中看到有关网址http://run.plnkr.co/thisis404
的错误:
要调试这个,我想快速找到在源中进行此XHR调用的位置(即找到app.js
文件):
所以我启用了chrome dev工具:
调试器实际上在XHR请求上停止,但调用堆栈只显示对angular.js" core"的引用。文件:无法参考 app.js
可在任何地方找到。
我尝试使用铬36和铬35.只有解决方案:在整个代码库中搜索错误的URL(在某些情况下可能很难)。
app.js
somwhere?app.js
文件?对于vanilla XHR请求(即没有角度),XHR调试调用堆栈在app.js
中显示XHR调用(在这种情况下更容易调试):
此处的完整示例:http://plnkr.co/edit/lnCRpv?p=preview
[编辑] 正如我被问到的那样:Angular.js在我的测试中并没有缩小。
答案 0 :(得分:11)
所以,你看,这个问题主要是因为angular的$ http很糟糕。对不起。
让我们尝试使用bluebird库,因为它提供了很长的堆栈跟踪。
Promise.longStackTraces();
Promise.resolve($http.get('...'));
您将获得以下堆栈跟踪:
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)
(Plunker here。)
最重要的一行是第一行:Possibly unhandled Error: [object Object]
。
是的。抛出一个对象,而不是真正的Error
对象,并附加stack
属性。作为参考,这里是如何抛出错误并保持其堆栈:https://github.com/Ralt/newerror/blob/master/index.js
那么,如何解决这个问题呢?这取决于几个决定:
如果您想添加真正的Promise lib,请使用bluebird。 AFAIK,它是为数不多的提供长堆栈跟踪的产品之一,也是最快的堆栈跟踪之一。
对于一个引起真正错误的正确的xhr库,我担心你在那里运气不好。编写一个支持您想要的浏览器的自定义版本并不是很难。由于没有IE8支持,这适用于(使用bluebird):
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。)
如您所见,堆栈跟踪信息丰富:
答案 1 :(得分:1)
XHR请求堆叠在$http.pendingRequests
数组中,稍后发送。这就是为什么您无法找到调用$http
的位置与实际XHR请求的位置之间的直接链接。
如果您想知道哪个函数$http
,您必须在$http
函数中设置断点。
它打败了整个" XHR断点"在我看来的目的。
答案 2 :(得分:0)
我想到的一个选项是为$ http调试创建一个模块,您可以在需要调试$ http调用时将其作为依赖项添加到主模块中。可以注册$ http服务的装饰器,只需记录呼叫的参数,然后将其转发到$ http服务。还可以设置断点。
我创建了一个简单的工作示例here。我希望它会有所帮助。
示例$ http logger装饰器实现:
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;
});