Wscats/articles

Angular打印错误的minErr函数

Wscats opened this issue · 1 comments

angular minErr函数的源码是这样的,这个函数主要用来输出错误的提示信息

function minErr(module) {
    return function() {
        var message, i, code = arguments[0],
            prefix = "[" + (module ? module + ":" : "") + code + "] ",
            template = arguments[1],
            templateArgs = arguments,
            stringify = function(obj) {
                return "function" == typeof obj ? obj.toString().replace(/ \{[\s\S]*$/, "") : "undefined" == typeof obj ? "undefined" : "string" != typeof obj ? JSON.stringify(obj) : obj
            };
        for (message = prefix + template.replace(/\{\d+\}/g, function(match) {
                var arg, index = +match.slice(1, -1);
                return index + 2 < templateArgs.length ? (arg = templateArgs[index + 2], "function" == typeof arg ? arg.toString().replace(/ ?\{[\s\S]*$/, "") : "undefined" == typeof arg ? "undefined" : "string" != typeof arg ? toJson(arg) : arg) : match
            }), message = message + "\nhttp://errors.angularjs.org/1.2.1/" + (module ? module + "/" : "") + code, i = 2; i < arguments.length; i++) message = message + (2 == i ? "?" : "&") + "p" + (i - 2) + "=" + encodeURIComponent(stringify(arguments[i]));
        return new Error(message)
    }
}

从这个函数中可以学到几点东西
首先是里面这个正则
template.replace(/\{\d+\}/g)
这个正则是匹配所有"{1个或更多数字}"形式的字符串
例如

var a = "{1}233{2}";
message = a.replace(/(\{)(\d+)(\})/g, 'wscats');//加了括号方便理解

相当于
new RegExp("\{\d+\}", "g")//g代表 global match(全定匹配)

其次是return new Error(message),这个

ngMinErr = minErr("ng");
throw ngMinErr("badname","hasOwnProperty is not a valid {0} name","module");

抛出打印的异常

function checkInput(x) {
    try {
        if (isNaN(parseInt(x))) {
            throw new Error("Input is not a number.");
        }
    } catch (e) {
        document.write(e.description);
        console.log(new Error("Input is not a number."));
    }
}
checkInput("not a number");

输出如下的异常信息
Uncaught Error: [ng:badname] hasOwnProperty is not a valid module name
http://errors.angularjs.org/1.2.1/ng/badname?p0=module"

这里如果throw new Error("wscats");之后,后面的代码就会得不到执行

无意之中看到了一篇文章
http://my.oschina.net/myprogworld/blog/207692

在1.2.5的版本中这里的第一个函数是这样写的

function minErr(module) {
  return function () {
    var code = arguments[0],
      prefix = '[' + (module ? module + ':' : '') + code + '] ',
      template = arguments[1],
      templateArgs = arguments,
      stringify = function (obj) {
        if (typeof obj === 'function') {
          return obj.toString().replace(/ \{[\s\S]*$/, '');
        } else if (typeof obj === 'undefined') {
          return 'undefined';
        } else if (typeof obj !== 'string') {
          return JSON.stringify(obj);
        }
        return obj;
      },
      message, i;

    message = prefix + template.replace(/\{\d+\}/g, function (match) {
      var index = +match.slice(1, -1), arg;

      if (index + 2 < templateArgs.length) {
        arg = templateArgs[index + 2];
        if (typeof arg === 'function') {
          return arg.toString().replace(/ ?\{[\s\S]*$/, '');
        } else if (typeof arg === 'undefined') {
          return 'undefined';
        } else if (typeof arg !== 'string') {
          return toJson(arg);
        }
        return arg;
      }
      return match;
    });

    message = message + '\nhttp://errors.angularjs.org/1.2.5/' +
      (module ? module + '/' : '') + code;
    for (i = 2; i < arguments.length; i++) {
      message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
        encodeURIComponent(stringify(arguments[i]));
    }

    return new Error(message);
  };
}

其实区别只是在于把message = prefix + template.replace(/{\d+}/g...这段放在for里面而已,其实我是喜欢1.2.5这一段代码的写法,因为比较清晰明了

而后面angular调用这个方法会根据传的是两个参数还是三个参数进行打印
例如这样
throw ngMinErr("btstrpd", "App Already Bootstrapped with this Element '{0}'", tag)
这里面的{0}就会被代码中的正则处理了