1

私はJavaScriptプログラミングが初めてで、Googleに尋ねる方法さえわからないので、私が達成したいことを詳細に説明します.

node.js および xml2js モジュールを使用して、単純な XML ファイルを解析するジャスミンの DataProvider クラスを作成しています。

<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ますが、ここでの欠点は、2 回使用する必要があることです (「移動」するスコープが 2 つあるため:

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 に答える