angularjs $ log - 显示行号

时间:2013-12-23 07:16:32

标签: javascript angularjs google-chrome

我在chrome中使用angularjs $ log,但它显示的行如:angular.js:9037,我想显示我调用此方法的行号。(显示我的js名称和正确的行),是谁知道呢?或角度没有此功能。

7 个答案:

答案 0 :(得分:16)

在Chrome中,有一项名为Blackboxing的功能。 您可以使用它从调试会话或开发工作流中排除/绕过(库)源。

因此,如果您使用blackbox angular,则会绕过$ log服务的内部,并且控制台会打印正确的行号!

https://developer.chrome.com/devtools/docs/blackboxing

答案 1 :(得分:3)

您可以通过将装饰器应用于$log服务来访问它:

module.config(function logConfig($provide, $logProvider) {
    $provide.decorator('$log', function ($delegate) {
        var originalFns = {};

        // Store the original log functions
        angular.forEach($delegate, function (originalFunction, functionName) {
            originalFns[functionName] = originalFunction;
        });

        var functionsToDecorate = ['debug', 'warn'];

        // Apply the decorations
        angular.forEach(functionsToDecorate, function (functionName) {
            $delegate[functionName] = logDecorator(originalFns[functionName]);
        });

        return $delegate;
    });

    function logDecorator(fn) {
        return function () {

            var args = [].slice.call(arguments);

            // Insert a separator between the existing log message(s) and what we're adding.
            args.push(' - ');

            // Use (instance of Error)'s stack to get the current line.
            var stack = (new Error()).stack.split('\n').slice(1);

            // Throw away the first item because it is the `$log.fn()` function, 
            // but we want the code that called `$log.fn()`.
            stack.shift();

            // We only want the top line, thanks.
            stack = stack.slice(1, 2);

            // Put it on the args stack.
            args.push(stack);

            // Call the original function with the new args.
            fn.apply(fn, args);
        };
    }
});

我这是一个可包含的模块,但我相信它也可以在应用程序.config()内完成。

我通过在线粘合多个不同来源构建了这个(以及一些额外的逻辑);我通常非常擅长保留对它们的引用,但我想我在构建它时并没有这么做,所以不幸的是我无法引用我的灵感。如果有人回复,我会把它放在这里。

  

注1:   这是我实际使用的略微简化的版本,所以你必须仔细检查logDecorator()的堆栈   狡猾的魔法虽然它应该如所呈现的那样有效。

     

注意B:   Error.prototype.stack {{1}}是非标准的(需要IE10,可能在许多移动浏览器上不受支持),因此您可能希望通过类似MDN says的内容来扩充它以获取堆栈本身

答案 2 :(得分:2)

我已经结合了这个页面的几个解决方案,以及其他人在JSFiddle中构建一个简单的演示 - 演示使用$ log服务,用装饰器增强它来添加行号(来自$ log调用的行号)制作)。我还在Plunker中做了一个稍微全面的解决方案,演示了使用$ log服务,用装饰器增强它来添加行号,调用者文件名和实例名。希望这对其他人有用。

JSFiddle网址 - https://jsfiddle.net/abhatia/6qnz0frh/

这个小提琴已经过以下浏览器的测试:

  • IE 11 - (JSFiddle Javascript的第一行号是72)。
  • Firefox 46.0.1 - (JSFiddle Javascript的第一行号是72)。
  • Chrome 50.0.2661.94米 - (JSFiddle Javscript的第一行号码是71)。

结果很好。但请注意,与FF或IE相比,Chrome中的行号将减1,即因为JSFiddle的javascript代码第一行号在FF / IE和Chrome之间有所不同,如上所列。

Plunker网址 - https://embed.plnkr.co/YcfJ7V/

这个插件很好地演示了这个概念,详细解释并且还提供了Angular的默认$ log服务的官方示例的控制台输出,因此这两者可以进行对比。 Plunk也已经过上面列出的浏览器测试过。

下面的屏幕截图是上面Plunk示例中的控制台输出。有三个突出的领域:

  • 红色框显示使用默认$ log服务的控制台输出。从控制器调用$ log函数。
  • 蓝框显示使用扩展$ log服务的控制台输出。从控制器调用的$ log函数。您可以看到脚本名称和行号的显示方式,以及控制器名称(在实例化$ log时使用)。
  • 橙色框将控制台输出与默认值对比,并扩展$ log服务。

Console log from plunker output

当您查看Plunk代码时,这将变得非常清晰。

这是JSFiddle中使用的getLineNumber函数(稍微增强的版本使用Plunker示例来返回调用者文件名):

function getLineNumber(newErr, sliceIndex1, sliceIndex2)
{
  var lineNumber = -1;
  var lineLocation;

  var stack = newErr.stack.split('\n').slice(2);
  if (navigator.userAgent.indexOf("Chrome") > -1) {
    stack.shift();
  }
  stack = stack.slice(sliceIndex1, sliceIndex2);
  var stackInString = stack + '';
  var splitStack;
  if (navigator.userAgent.indexOf("Chrome") > -1) {
    splitStack = stackInString.split(" ");
  }
  else {
    splitStack = stackInString.split("@");
  }
  lineLocation = splitStack[splitStack.length - 1]; 
  //console.log(lineLocation);
  lineNumber = lineLocation.split(":")[2];
  return lineNumber; 
}

答案 3 :(得分:1)

行号来自运行时。一般情况下你不能设置它。

但并非所有人都失去了。在行号非常重要的地方,您可以使用不同的呼叫。 记得注入$window然后注入:

$window.console.log("test1");

你通过格式化,跨浏览器填充代码等方式放弃了一些东西,但是你确实可以免费获得正确的行号,而不需要每个运行时特定的代码。

答案 4 :(得分:1)

接近floatingLomas's回答

module.config(function($logProvider, $provide){ 
    $provide.decorator('$log', function ($delegate) {
        $delegate.info = function () {
            var args = [].slice.call(arguments);
            if (window.console && window.console.table)
                console.trace(args[0], args[1]);
            else
                $delegate.log(null, args)
        };
        return $delegate;
    });
})

enter image description here

通常第二个@行是你需要的,在这种情况下是90618

答案 5 :(得分:1)

我使用了floatLomas解决方案并进行了一些调整,因为它在FF上不起作用,堆栈略有不同。像IE这样的幻像不支持Error.stack并且爆炸。 日志位置可以在chrome中单击,但不能在ff中单击。

app.config(function logConfig($provide, $logProvider) {
    $provide.decorator('$log', function ($delegate) {
        var originalFns = {};

        // Store the original log functions
        angular.forEach($delegate, function (originalFunction, functionName) {
            originalFns[functionName] = originalFunction;
        });

        var functionsToDecorate = ['debug', 'warn'];

        // Apply the decorations
        angular.forEach(functionsToDecorate, function (functionName) {
            $delegate[functionName] = logDecorator(originalFns[functionName]);
        });

        return $delegate;
    });

function logDecorator(fn) {
    return function () {

        var args = [].slice.call(arguments);

        // Insert a separator between the existing log message(s) and what we're adding.
        args.push(' - ');

        // Use (instance of Error)'s stack to get the current line.
        var newErr = new Error();

        // phantomjs does not support Error.stack and falls over so we will skip it
        if (typeof newErr.stack !== 'undefined') {
            var stack = newErr.stack.split('\n').slice(1);

            if (navigator.userAgent.indexOf("Chrome") > -1) {
                stack.shift();
            }
            stack = stack.slice(0, 1);

            var stackInString = stack + '';
            var splitStack;
            if (navigator.userAgent.indexOf("Chrome") > -1) {
                splitStack = stackInString.split(" ");
            } else {
                splitStack = stackInString.split("@");
            }
            var lineLocation = splitStack[splitStack.length - 1];
            // Put it on the args stack.
            args.push(lineLocation);

            // Call the original function with the new args.
            fn.apply(fn, args);
        }
    };
}

答案 6 :(得分:0)

我使用chrome版本65.0.3325.181

在我的情况下,

  
      
  1. 转到菜单,设置 - > blackboxing
  2.   
  3. 检查黑盒内容脚本
  4.   
  5. 添加blockbox pattern angular.js
  6.   

check and add blackbox pattern :)