我是JavaScript编程的新手,我甚至不知道如何问Google,所以我将详细描述我想要实现的目标。
我正在使用node.js和xml2js模块为jasmine创建DataProvider类,该类解析简单的XML文件:
<Tests>
<Test name="test1">
<values>2,4,6</values>
<expectations>1,2,3</expectations>
</Test>
<Test name="test2">
<values>8,10,12</values>
<expectations>4,5,6</expectations>
</Test>
</Tests>
我希望数据提供程序构造函数立即解析 XML 并在 this.testData
中显示结果。脚本为:
var fs = require('fs'),
xml2js = require('xml2js'),
util = require('util');
var DataProvider = function(dataPath) {
this.dataPath = dataPath;
this.testData;
fs.readFile(this.dataPath, function(err, data) {
var parser = new xml2js.Parser();
parser.parseString(data, function(err, result) {
//console.log(util.inspect(result, false, null));
this.testData = result;
});
});
};
我像这样使用它:
var dp = new DataProvider("C:\data2.xml");
console.log(dp.testData);
当我运行脚本时>node script.js
我收到undefined
.当我取消评论时console.log(util.inspect(result, false, null));
我收到
undefined
{ Tests:
{ Test:
[ { '$': { name: 'test1' },
values: [ '2,4,6' ],
expectations: [ '1,2,3' ] },
{ '$': { name: 'test2' },
values: [ '8,10,12' ],
expectations: [ '4,5,6' ] } ] } }
所以一般来说它有效,但是如何将result
分配给this.testData
?
这与this.testData
范围有关吗?
JavaScript 经常使用异步范式,因此当您读取文件时 - 您作为回调提供的函数将在自己的范围内执行。 this
与范围有关,因此您将丢失它。在您尝试引用后this.testData
实际上不会引用 DataProvider 对象,而是引用您提供给 parseString 的匿名函数的范围。
所以有几种方法可以克服,这里最简单的方法是在上层范围内持久化this
变量,因此您可以引用它,例如调用它self
,一些开发人员更喜欢that
。
var DataProvider = function(dataPath) {
this.dataPath = dataPath;
this.testData;
var self = this;
fs.readFile(this.dataPath, function(err, data) {
var parser = new xml2js.Parser();
parser.parseString(data, function(err, result) {
//console.log(util.inspect(result, false, null));
self.testData = result;
});
});
};
或者通过使用 .bind
,但这里的缺点是它必须使用两次(因为您有两个范围要"穿越":
var DataProvider = function(dataPath) {
this.dataPath = dataPath;
this.testData;
fs.readFile(this.dataPath, function(err, data) {
var parser = new xml2js.Parser();
parser.parseString(data, function(err, result) {
//console.log(util.inspect(result, false, null));
this.testData = result;
}.bind(this));
}.bind(this));
};