跟踪是在运行时记录应用程序诊断信息的过程。对于开发人员来说,这是一种非常有用的调试形式,因为它可以揭示有关应用程序内部工作原理的大量信息。这对于应用程序的非可视化部分(如网络和文件 I/O)尤其适用。跟踪使开发人员能够在运行时观察应用程序以识别问题。
在深入研究跟踪之前,让我们简要检查一下 console 模块,因为它被 NativeScript 的跟踪基础架构广泛使用。
控制台(或终端)并不是什么新鲜事物。我们已经使用它几十年了。
尽管用户界面发生了变化,但控制台在帮助开发人员调试代码方面仍然发挥着至关重要的作用。
在 NativeScript 中,console 模块提供用于将诊断输出记录到终端窗口的功能。大多数情况下,开发人员会使用 console 模块通过 console.log()
记录消息。
console.log(
"Hello, NativeScript!"
);
以下是生成的输出
请注意,我不必引用 console 模块本身。这是因为它属于全局作用域,可以在 NativeScript 应用程序内的任何位置访问它。
还值得一提的是,console 模块具有一系列有用的函数,您可以在跟踪 NativeScript 应用程序时使用它们。
console.time()
和 console.timeEnd()
提供持续时间,这对于跟踪对时间敏感的操作(即性能)很有用。console.trace()
将当前堆栈跟踪打印到控制台;在跟踪时提供上下文很有用。console.dump()
打印对象的内部状态(目前仅限 Android)。当您开始使用 NativeScript 的跟踪基础架构时,我强烈建议您在应用程序中考虑使用这些函数。
NativeScript 的 trace 模块可用于记录您自己的应用程序及其使用的模块的信息。使用 NativeScript,核心、设备功能、数据、用户界面和 WHATWG polyfill 模块都包含一定程度的跟踪,可以观察到。
默认情况下,跟踪处于禁用状态;必须通过其 enable()
方法显式启用它。
var
trace = require(
"trace"
);
trace.enable();
// 跟踪已启用 -- 派对开始!
值得注意的是,您也可以通过其 disable()
方法禁用跟踪。
trace.disable();
// 跟踪已禁用 -- 扫兴的人!
启用跟踪后,任何调用 trace.write()
的代码或模块都会输出跟踪消息。
trace.write(
"I (heart) NativeScript!"
, trace.categories.Debug);
在我的应用程序中包含这行代码(上面)会在控制台中生成以下输出。
trace.write()
方法接受三个 (3) 个参数。
在提供的示例(上面)中,我为跟踪消息提供了一个字符串,但我可以为更多上下文提供更详细的对象。
通过调用 trace.write()
生成所有跟踪消息都通过 TraceWriter
对象的集合写入。这些对象的目的是将跟踪消息写入特定输出(即文件)。trace 模块维护一个 TraceWriter
对象的集合,它将跟踪消息定向到这些对象。默认情况下,在初始化跟踪时,将向此集合中添加 ConsoleWriter
。此写入器将通过 console 模块发出所有跟踪消息。有一组函数可用于控制此 TraceWriter
对象的集合。
trace.addWriter()
将 TraceWriter
对象添加到跟踪写入器集合中。trace.removeWriter()
从跟踪写入器集合中删除 TraceWriter
对象。trace.clearWriters()
从跟踪写入器集合中删除所有 TraceWriter
对象。目前,NativeScript 只有一个 TraceWriter
对象;ConsoleWriter
。但是,没有任何东西可以阻止您编写自己的 TraceWriter
。
trace 模块提供了一种通过 setCategories()
方法过滤其输出的功能。这将强制 TraceWriter
对象的集合仅输出与您提供的类别列表匹配的写入语句。该方法参数是一个类别逗号分隔字符串,用于确定何时以及是否通过 TraceWriter
对象生成输出。trace 模块(本身)定义了以下预定义类别列表。
这些类别(上面)由各种模块使用,因此在配置期间最好也使用它们。
必须提到的是,您不必使用预定义的类别(上面列出);您可以定义自己的类别。为此,只需定义您的类别,并确保在建立跟踪消息过滤器和调用 trace.write()
时一致地应用它,如下所示。
trace.setCategories(
"Questions"
);
trace.write(
"NativeScript: Great technology or the greatest technology?"
,
"Questions"
);
应用此代码段(上面)会导致以下内容输出到控制台。
您还可以通过 trace.addCategories()
方法将类别附加到现有集合中。或者,使用 trace.categories.concat()
方法构建您感兴趣的类别集合。
// 将绑定类别添加到现有的跟踪消息列表中。
trace.addCategories(trace.categories.Binding);
// 筛选除动画和调试类别外的所有跟踪消息。
trace.setCategories(trace.categories.concat(trace.categories.Animation, trace.categories.Debug));
如果您想更好地了解 NativeScript 的工作原理,请启用跟踪并指定 trace.categories.All
类别。当您执行此操作时,您将看到许多跟踪消息输出到控制台。
就像观看和理解香肠是如何制成的——以一种好的方式。
之前,我说过您可以编写自定义 TraceWriter
。您可能希望执行此操作以将跟踪消息路由到控制台以外的特定输出。或者,您可能希望修改输出本身。假设我想在所有跟踪消息的开头添加一个时间戳。执行此操作将提供我可以在跟踪消息之间使用的时差。(注意:您可能会使用 timer 模块执行此操作,但现在让我们先这样处理。)我将首先定义一个名为 TimestampConsoleWriter 的自定义 TraceWriter
。
var
TimestampConsoleWriter = (
function
() {
function
TimestampConsoleWriter() { }
TimestampConsoleWriter.prototype.write =
function
(message, category, type) {
if
(!console)
return
;
var
msgType = types.isUndefined(type) ? trace.messageType.log : type;
var
traceMessage =
new
Date().toISOString() +
" "
+ category +
": "
+ message;
switch
(msgType) {
case
trace.messageType.log:
console.log(traceMessage);
break
;
case
trace.messageType.info:
console.info(traceMessage);
break
;
case
trace.messageType.warn:
console.warn(traceMessage);
break
;
case
trace.messageType.error:
console.error(traceMessage);
break
;
}
};
return
TimestampConsoleWriter;
})();
由于我使用了**console**模块,因此我将清除我的TraceWriter
对象集合,以移除ConsoleWriter
。否则,每次调用trace.write()
时,控制台都会输出多个跟踪消息。然后,我将**TimestampConsoleWriter**添加到TraceWriter
对象的集合中。
trace.clearWriters();
trace.addWriter(
new
TimestampConsoleWriter());
此更改的结果是在控制台中显示以下输出
如您所见,**trace**模块功能强大,因为您可以覆盖其默认行为,并通过自定义类别和TraceWriter
对象来整合更改。
**trace**模块还支持一种机制,可以通过事件通知在运行时跟踪您的NativeScript应用程序。这是一种强大的跟踪形式,因为它允许您将跟踪事件广播到实现EventListener
接口的订阅者集合。事件监听器可以利用TraceWriter
对象生成跟踪消息,或者它们可以处理事件通知中传达的信息并完全执行不同的操作。
以下是事件监听器的样板代码
var
Listener = (
function
() {
function
Listener(filter) {
this
.filter = filter;
}
Listener.prototype.on =
function
(object, name, data) {
// 验证参数并为 trace.notifyEvent() 执行某些操作
};
return
Listener;
})();
on()
方法是事件监听器响应接收事件通知时执行工作的地方,该通知通过对trace.notifyEvent()
的调用传播(稍后将详细介绍)。filter属性是可选的,但应该包含它,因为它为**trace**模块提供了对通知哪些事件监听器的控制。就像TraceWriter
对象的输出一样,除非启用了跟踪,否则不会通过trace.notifyEvent()
通知事件监听器。
定义事件监听器后,下一步是通过trace.addEventListener()
将其添加到**trace**模块中的事件监听器集合中。
var
listener =
new
Listener(
"NativeScript Rocks!!11!"
);
trace.addEventListener(listener);
在代码(上文)中,我创建了一个新的事件监听器,它将接收名称为“NativeScript Rocks!!11!”的事件通知。除了添加事件监听器之外,我还可以通过trace.removeEventLister()
将其移除。
事件监听器响应通过对trace.notifyEvent()
的调用触发的事件通知。
var
data = {
/* ... */
};
trace.notifyEvent(
this
,
"NativeScript Rocks!!11!"
, data);
trace.notifyEvent()
方法接受三个(3)个参数
当调用trace.notifyEvent()
时,所有订阅了匹配名称/过滤器的事件监听器都会收到通知,并可以执行诸如记录到控制台等操作。
更好地理解您的NativeScript应用程序在幕后是如何工作的,是构建用户喜爱的健壮应用程序的关键。**跟踪**模块提供了一些强大的机制,您可以使用这些机制来调试问题或验证假设。如果其他方法都不起作用,只需启用它就能更好地了解NativeScript的关键概念(如绑定或样式)是如何工作的。