1

我是 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>

我希望 DataProvider 构造函数立即解析 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' ] } ] } }

所以通常它可以工作,但是如何分配resultthis.testData

这与范围有关this.testData吗?

4

1 回答 1

1

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));
};
于 2014-01-03T10:51:07.230 回答