Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the full call stack trace of $http calls

Let's say someone wrote a method like this in a file called app.js trying to peform an XHR request angainst a non existing url:

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

I can see an error regarding URL http://run.plnkr.co/thisis404 in console and network panel :

error in console

To debug this I want to find quickly where this XHR call was made in sources (ie find the app.js file) :

So I enable in chrome dev tools :

  • async debug in call stack
  • debug any XHR

Debugger actually stops on XHR request, but the call stack only displays references to angular.js "core" files : no reference to app.js anywhere to be found.

google chrome call stack

I tried this with chromium 36 and chrome 35. Only solution : search for the wrong URL in the whole code base (which in some case may be hard to do).

  • Isn't the async debug mode supposed to point to app.js somwhere in the stack ?
  • Is there a way to track down this app.js file easily from the console error ?

With vanilla XHR requests (ie without angular), XHR debug call stack displays the XHR call in app.js (which is easier to debug in this case) :

enter image description here

Full example here : http://plnkr.co/edit/lnCRpv?p=preview

[EDIT] As i've been asked : Angular.js is not minified in my tests.

like image 801
sylvain Avatar asked Jun 23 '14 11:06

sylvain


People also ask

How do I recover stack trace?

You can obtain a stack trace from a thread – by calling the getStackTrace method on that Thread instance. This invocation returns an array of StackTraceElement, from which details about stack frames of the thread can be extracted.

How do you get a stack trace in windbg?

You can view the call stack by entering one of the k (Display Stack Backtrace) commands in the Debugger Command window.

What is full stack trace?

A full stack trace allows you to see the chain of files from when your custom tag reached your set breakpoint. If you click on any of the pages in the caller chain then FusionDebug will show you that page and will highlight the line at which the next page in the chain was called.


1 Answers

So, you see, this issue is mostly because angular's $http sucks. Sorry about that.

Let's try to use the bluebird library, because it provides long stack traces.

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

You get the following stack trace:

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.)

The most important line is the first: Possibly unhandled Error: [object Object].

Yep. An object is thrown, not a real Error object, with the stack property attached to it. For the reference, here is how to throw an error and keep its stack along with it: https://github.com/Ralt/newerror/blob/master/index.js

So, how to fix this? It depends on several decisions:

  • Do you want to add a proper Promise lib that enables long stack traces?
  • Do you want to use another xhr lib that throws correct errors?

If you want to add a real Promise lib, use bluebird. AFAIK, it is one of the few that provides long stack traces, and it is the fastest one out there.

For a proper xhr lib that throws real errors, I'm afraid you're out of luck there. Writing a custom one with the support for browsers you want isn't really hard though. With no IE8 support, this works (with 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.)

As you can see, the stack trace is informative:

correct stack trace

like image 190
Florian Margaine Avatar answered Sep 19 '22 12:09

Florian Margaine