简体   繁体   English

如何解决Node.js中的“无法读取未定义的属性”

[英]How to resolve “Cannot read property of undefined” in Node.js

I'm newbie in JS and I need to create simple CSV parser for test data. 我是JS的新手,我需要为测试数据创建简单的CSV解析器。 And I have a very strange problem. 我有一个非常奇怪的问题。

This is code of my test: 这是我测试的代码:

'use strict';

const assert = require('assert');
const HomePage = require('../pages/HomePage');
const csv = require('../tools/CsvReader');

describe('Check if values are correct', () => {

    let dataProvider = csv.readFromCsv("test/resources/places.csv");

    function valuesTest(city, expectedLat, expectedLong) {
        it('Data must match', () => {
            let searchPlace = HomePage
                .open()
                .findByPlaceName(city)
                .getSearchPlace();
            assert.strictEqual(searchPlace.getLatitude(), expectedLat);
            assert.strictEqual(searchPlace.getLongtitude(), expectedLong);
            console.log(dataProvider[0].CITY);
        });
    }

    for (let i = 0; i < dataProvider.length; i++) {
        valuesTest(dataProvider[i].CITY, dataProvider[i].LAT, dataProvider[i].LONG)
    }

});

And code of my CSV-reader: 和我的CSV阅读器的代码:

'use strict';

const csv = require('csv-parser');
const fs = require('fs');

class CsvReader {


    readFromCsv(path) {
        let results = [];

        fs.createReadStream(path)
            .pipe(csv())
            .on('data', (data) => results.push(data));
        return results;
    }

}

module.exports = new CsvReader();

And this is my CSV: 这是我的CSV:

CITY,LAT,LONG
Kyiv,50.447731,30.542721
Lviv,49.839684,24.029716
Ivano-Frankivsk,48.922634,24.711117

The problem is as follows: Why can I use the variable "dataProvider" in the "valuesTest" block and it works correctly and returns the value of the CITY variable, but in the "for" loop I can't use it (variable "dataProvider", "CITY", etc. is unavailable there), although they are located in the same block "describe". 问题如下:为什么我可以在“ valuesTest”块中使用变量“ dataProvider”,它可以正常工作并返回CITY变量的值,但是在“ for”循环中,我不能使用它(变量“ dataProvider”,“ CITY”等在此处不可用),尽管它们位于同一块“描述”中。

Your CSV Reader is an asynchronous operation. CSV阅读器是异步操作。 I suspect your for loop gets executed even before the csv is parsed and value is returned. 我怀疑您的for循环即使在解析csv并返回值之前也已执行。 Try putting your for loop in a function and passing to the readFromCsv function as a callback. 尝试将for循环放入函数中,并作为回调传递给readFromCsv函数。 Call this function on the data event, where you will be sure to get the data. 在数据事件上调用此函数,您将在该事件上确保获得数据。

You should pass a callback to readFromCsv that will be executed when the createReadStream is complete. 您应该将回调传递给readFromCsv ,当createReadStream完成时将执行该回调。 You can determine when createReadStream is complete by listening to its end event. 您可以通过侦听其end事件来确定createReadStream何时完成。 (See csv-parser example code for instance). 例如,请参阅csv-parser示例代码 )。

In your case, you could do something like: 就您而言,您可以执行以下操作:

readFromCsv(path, onEnd) {
    let results = [];

    fs.createReadStream(path)
        .pipe(csv())
        .on('data', (data) => results.push(data))
        .on('end', () => onEnd(results));
}

csv.readFromCsv("test/resources/places.csv", function onData(data) {
    for (let i = 0; i < data.length; i++) {
        valuesTest(data[i].CITY, data[i].LAT, data[i].LONG);
    } 
});

You should use the end event instead of the data event to determine when the stream is complete. 您应该使用end事件而不是data事件来确定流何时完成。 If you returned after the first data event, you might not get all of the data. 如果您在第一个data事件之后返回,则可能无法获取所有数据。

The data event is fired once per data chunk. 每个数据块都会触发一次data事件。 If your data has more than one "chunk", you'll truncate it if you return in the data callback. 如果您的数据中有多个“块”,则如果返回数据回调,则会将其截断。 See nodeJS docs for details on the different event types. 有关不同事件类型的详细信息,请参见nodeJS文档 You might not notice a difference with small test files, but make a larger file and you'll see the difference. 您可能不会注意到较小的测试文件会有所不同,但是制作较大的文件会看到差异。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM