使用 HTML5 File API 实现客户端 log(3)
 
- UID
- 1066743
|

使用 HTML5 File API 实现客户端 log(3)
使用 HTML5 File API 实现输出客户端 log 信息到文件在传统的客户端 log 设计中,只能将客户端 log 输出到浏览器的控制台,但在客户环境中,客户端程序一旦出错,客户将收集不到这些 log 信息,对于开发人员来说, 一旦客户端程序出错,需要模拟客户的真实环境,重现错误信息,这将是一件非常有挑战的工作,因为客户的实际环境千差万别。本文将根据上面传统客户端 log 的设计,使用 HTML5 File API 实现 将客户端 log 输出到文件中,一旦客户端程序出错,可以很容易的收集到这些 log 信息。
1. 实现 Web Workers
本文中需要使用同步版本的 File API,所以需要实现一个 Web Workers 用来将信息输出到文件中。在 html5.Log 类中,通过 postMessage/onmessage API 实现和 Web Workers 的数据交互。
清单 5. 实现 Web Workers1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| // 解决 File API 浏览器兼容性问题
self.requestFileSystemSync = self.webkitRequestFileSystemSync
|| self.requestFileSystemSync;
self.BlobBuilder = self.BlobBuilder || self.WebKitBlobBuilder
|| self.MozBlobBuilder;
var html5logFolder = null;
self.onmessage = function(e) {
var data = e.data;
switch (data.cmd){
// 初始化 log 文件夹
case "init":{
var fs = self.requestFileSystemSync(PERSISTENT, data.grantedBytes);
html5logFolder = fs.root.getDirectory('html5logs', {create: true});
break;
}
// 写内容到 log 文件
case "log":{
var fileEntry = html5logFolder.getFile(data.logFileName, {create: true});
var fileWriter = fileEntry.createWriter();
var blob = new BlobBuilder();
blob.append(data.logEntryStr);
fileWriter.seek(fileWriter.length);
fileWriter.write(blob.getBlob('text/plain'));
break;
}
}
};
|
在 Web Workers JavaScript 文件中,通过 onmessage 方法,接受 html5.Log 类中发过来的命令。在 init 命令中,将申请相应的磁盘空间,并创建一个 html5logs 的文件夹,其中 create:true 表示如果文件夹不存在则创建,存在则返回文件夹示例。在 log 命令中,将把 log 内容输出到具体的 log 文件中。同理 getFile 方法中的 create:true 参数意义和 getDirectory 方法一样。
2. 重构 html5.Log 类,实现与 Web Workers 交互
首先,需要在 html5.Log 类中创建一个 Web Workers。在 METHODMAP 属性后面加上私有的属性 _logData 和 _logWorker。 其中 _logData 用来表示 Web Workers 中的 init 命令是否已经被调用了,而 _logWorker 用来表示真正的 Web Workers 实例。
清单 6. 添加类属性1
2
3
| METHODMAP:{"1":"error","2":"warn","3":"info","4":"debug"},
_logData:{"status":false},
_logWorker:new Worker('HTML5File.js'),
|
然后,在 html5.Log 类的构造函数中使用 postMessage 方法,向 Web Workers 发送 init 命令。
清单 7. 向 Web Workers 发送 init 命令1
2
3
4
5
6
7
8
9
10
11
12
13
| constructor: function(grantedBytes) {
//1 表示记录错误信息,2 表示记录警告信息,3 表示记录一般信息,4 表示记录调式信息
this.logLevel = 1;
this.indent = 0;
if(!this._logData.status){// 所有实例只初始化一次
this._logData.status = true;
this._logWorker.postMessage({"cmd":"init","grantedBytes":grantedBytes});
}
this._logWorker.onmessage = function(e) {
// 用来接收 Web Workers 返回的数据
}
}
|
最后,在 html5.Log 类的 _record 方法中,调用 _writeLogEntryToFile 方法并在这个方法里使用 postMessage 方法,向 Web Workers 发送 log 命令,传递 log 文件名称以及要记录的 log 信息作为参数。
清单 8. 向 Web Workers 发送 log 命令1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| _record: function(level, location, message, extra) {
var logEntry = {
level: level,
time: new Date(),
loc: location,
msg: message,
extra: extra,
indent: this.indent
};
if (level <= this.logLevel) {
var logInfo = this._formatLogEntry(logEntry);
this._writeLogEntryToFile(logEntry,logInfo);
}
},
_writeLogEntryToFile:function(logEntryObj,logEntryStr){
// 每一天创建一个 log 文件
var logFileName = dojo.date.locale.format(logEntryObj.time,
{datePattern: "yyyy-MM-dd'.log'","selector":"date"});
this._logWorker.postMessage({"cmd":"log","logFileName":logFileName,"logEntryStr":logEntryStr});
}
|
|
|
|
|
|
|