Подтвердить что ты не робот

Получить трассировку стека вызовов вызовов $http

Скажем, кто-то написал метод, подобный этому, в файле под названием app.js, который пытается отобразить запрос XHR angainst не существующего url:

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

Итак, я включаю в хром dev tools:

  • асинхронная отладка в стеке вызовов
  • отладить любой XHR

Отладчик фактически останавливается на запросе XHR, но в стеке вызовов отображаются ссылки на файлы angular.js: ссылка на app.js в любом месте, где можно найти strong > .

google chrome call stack

Я попробовал это с хромом 36 и хром 35. Только решение: поиск неправильного URL-адреса во всей базе кода (что в некоторых случаях может быть трудным).

  • Не должен ли режим отладки async указывать на app.js somwhere в стеке?
  • Есть ли способ легко отследить этот app.js файл из-за ошибки консоли?

С помощью запросов ванильного XHR (т.е. без angular), стек XHR-отладки вызывает вызов XHR в app.js (который в этом случае легче отлаживать):

enter image description here

Полный пример здесь: http://plnkr.co/edit/lnCRpv?p=preview

[EDIT] Как я уже спросил: angular.js не проверяется в моих тестах.

4b9b3361

Ответ 1

Итак, вы видите, эта проблема в основном связана с тем, что 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 здесь.)

Самая важная строка - первая: Possibly unhandled Error: [object Object].

Угу. Объект бросается, а не реальный объект Error, с прикрепленным к нему свойством stack. Для справки, вот как сделать ошибку и сохранить ее стек вместе с ней: https://github.com/Ralt/newerror/blob/master/index.js

Итак, как это исправить? Это зависит от нескольких решений:

  • Вы хотите добавить правильную библиотеку Promise, которая позволяет отслеживать длинные стеки?
  • Вы хотите использовать другую xhr lib, которая порождает правильные ошибки?

Если вы хотите добавить настоящую Promise lib, используйте bluebird. AFAIK, это один из немногих, который обеспечивает длинные трассировки стека, и он самый быстрый из них.

Для правильного xhr lib, который порождает реальные ошибки, я боюсь, что вам там не повезло. Написание пользовательского с поддержкой браузеров, которые вы хотите, на самом деле не очень сложно. Без поддержки 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 здесь.)

Как вы можете видеть, трассировка стека информативна:

correct stack trace

Ответ 2

Запросы XHR сложены в массив $http.pendingRequests и отправляются позже. Вот почему вы не можете найти прямую связь между тем, где вызывается $http и где выполняется фактический запрос XHR.

Если вы хотите узнать, какая функция называется $http, вам нужно установить точку останова в $http.

Похоже на то, что поражение цели "точки останова XHR" на мой взгляд.

Ответ 3

Один из вариантов, который пришел мне на ум, - создать модуль для отладки $http, который вы можете добавить в зависимости от вашего основного модуля, когда вам нужно отлаживать $http-вызовы. Там может быть зарегистрирован декоратор для службы $http, который будет просто регистрировать аргументы вызова, пересылать его в службу $http. Там также может быть установлена ​​точка останова.

Я создал простой рабочий пример здесь. Надеюсь, это поможет.

Пример реализации декодера $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;
});