Electron / JS等到变量从另一个函数获取数据

时间:2019-03-15 15:59:45

标签: javascript arrays electron

我目前正在学习将Electron用于大学项目。我想做的是从.xlsx文件中读取数据,然后使用chart.js创建图表并显示数据。为此,我正在使用exceljs和chart.js。为此,我编写了多个函数(下面的代码)。我现在的问题是,我尝试返回一个包含一些数据的数组(它创建得很好),但是在其他函数中它只显示为undefined

我知道,我的代码不好。老实说,这是完整的意大利面。我只需要使它正常工作,就不必使用漂亮的代码。

这是我用来绘制图表的功能:

function createGraph() {
    // Create Canvas if not already created
    if (document.getElementById('datacanvas') == null) {
        var canvas = document.createElement('canvas');
        canvas.setAttribute("id", "datacanvas")
        var datadiv = document.getElementById("datadiv");
        datadiv.appendChild(canvas);
        var ctx = canvas.getContext("2d");
    }
    else {
        var canvas = document.getElementById('datacanvas')
        var ctx = canvas.getContext("2d");
    }

    var labls = ["Januar", "Februar", "März", "April", "Mai", "Juni",
        "Juli", "August", "September", "Oktober", "November", "Dezember"];
    var datasts = createDatasets();
    console.log(datasts);

    var chart = new Chart(ctx, {
        type: 'line',
        data: {
            labels: labls,
            datasets: datasts
        },
        options: {
            scales: {
                yAxes: [{
                    ticks: {
                        beginAtZero: true
                    }
                }]
            }
        }
    });

}

我遇到的问题是变量datasts或更确切地说data属性,因为数据是不确定的。它是通过以下两个功能创建的:

function createDatasets() {
    console.log("createDatasets");
    var dataset = [];

    var rdbStrom = document.getElementById('rdbStrom');
    var rdbGas = document.getElementById('rdbGas');
    var rdbWasser = document.getElementById('rdbWasser');
    var rdbGesamt = document.getElementById('rdbGesamt');

    if (rdbStrom.checked) {
        var set = {
            label: 'Stromkosten',
            data: getDataArray("strom"),
            borderColor: '#FF0000',
            borderWidth: 1
        };
        dataset.push(set);
    }

    if (rdbGas.checked) {
        var set = {
            label: 'Gaskosten',
            data: getDataArray("gas"),
            borderColor: '#00FF00',
            borderWidth: 1
        };
        dataset.push(set);
    }

    if (rdbWasser.checked) {
        var set = {
            label: 'Wasserkosten',
            data: getDataArray("wasser"),
            borderColor: '#0000FF',
            borderWidth: 1
        };
        dataset.push(set);
    }

    if (rdbGesamt.checked) {
        ;
        var set = {
            label: 'Gesamtkosten',
            data: getDataArray("gesamt"),
            borderColor: '#FFFFFF',
            borderWidth: 1
        };
        dataset.push(set);
    }

    // Wait
    setTimeout(() => {
        return dataset;
    }, 1000);

}

function getDataArray(type) {
    console.log("getDataArray");

    var data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
    var period = [];
    var start = new Date(document.getElementById('start').value);
    var end = new Date(document.getElementById('end').value);
    var tmp = new Date(start);

    do {
        period.push(tmp.toDateString());

        tmp.setDate(tmp.getDate() + 1);
    } while (tmp <= end)

    if (!fs.existsSync('./Data.xlsx')) {
        alert("Error finding File 'Data.xlsx'.");
    }
    else {
        switch (type) {
            case "strom": {
                workbook.xlsx.readFile('./Data.xlsx')
                    .then(function () {
                        var worksheet = workbook.getWorksheet('Data');

                        for (var i = 2; i <= worksheet.rowCount; i++) {
                            var r = worksheet.getRow(i);
                            var d = new Date(r.getCell(1).value);

                            if (period.includes(d.toDateString())) {
                                var vbr = r.getCell(3).value;
                                var prc = r.getCell(4).value;
                                var gprc = r.getCell(5).value;
                                var tax = r.getCell(6).value;
                                var kosten = (vbr * prc) + gprc + tax;
                                data[d.getMonth()] = data[d.getMonth()] + kosten;

                            }
                        }
                    })

                break;
            }
            case "gas": {
                workbook.xlsx.readFile('./Data.xlsx')
                    .then(function () {
                        var worksheet = workbook.getWorksheet('Data');

                        for (var i = 2; i <= worksheet.rowCount; i++) {
                            var r = worksheet.getRow(i);
                            var date = new Date(r.getCell(1).value);

                            if (period.includes(date.toDateString())) {
                                var vbr = r.getCell(8).value;
                                var prc = r.getCell(9).value;
                                var gprc = r.getCell(10).value;
                                var tax = r.getCell(11).value;
                                var kosten = (vbr * prc) + gprc + tax;
                                data[d.getMonth()] = data[d.getMonth()] + kosten;

                            }
                        }
                    })
                break;
            }
            case "wasser": {
                workbook.xlsx.readFile('./Data.xlsx')
                    .then(function () {
                        var worksheet = workbook.getWorksheet('Data');

                        for (var i = 2; i <= worksheet.rowCount; i++) {
                            var r = worksheet.getRow(i);
                            var date = new Date(r.getCell(1).value);

                            if (period.includes(date.toDateString())) {
                                var vbr = r.getCell(13).value;
                                var prc = r.getCell(14).value;
                                var gprc = r.getCell(15).value;
                                var tax = r.getCell(16).value;
                                var kosten = (vbr * prc) + gprc + tax;
                                data[d.getMonth()] = data[d.getMonth()] + kosten;

                            }
                        }
                    })
                break;
            }
            default:
                break;
        }
    }

    // Wait till process is done reading file
    setTimeout(() => {
        console.log("Timeout")
        for (i = 0; i < data.length; i++) {
            console.log("Data[" + i + " ]: " + data[i]);
        }
        console.log("Return DataArray");
        return data;
    }, 1000);

}

同样,我知道我的代码不好,我只需要使它工作即可。 控制台中的输出如下:

createDataset
getDataArray
undefined // This is the datasts Variable which I need to wait for
Timeout // This comes from the third function
// Here it displays the data it read from the Excel file from the third function

1 个答案:

答案 0 :(得分:0)

这是由于异步性问题,您在使用createDatasets时就好像它是一个同步函数(例如return 1 + 2),而它依赖于异步操作, 即:

let exampleInt = 0
setTimeout(() => {

        // callback
        exampleInt = 1;
        return dataset;
    }, 1000);

// This will be reached before the callback executes, so exampleInt equals 0

您应该查看https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises以实现您的目标,我想在操作结束之前等待操作结束,然后再根据操作结果执行代码

它会让您大开眼界吗?


现在的分辨率,第一个功能: createDatasets

function createDatasets() {
    console.log("createDatasets");
    var dataset = [];

    var rdbStrom = document.getElementById('rdbStrom');
    var rdbGas = document.getElementById('rdbGas');
    var rdbWasser = document.getElementById('rdbWasser');
    var rdbGesamt = document.getElementById('rdbGesamt');

    // storing each label we need
    let dataArraysNeeded = [];
    let dataArraysNeededAsPromises = [];

    let designParams = {
        "strom": {
            title: "Stromkosten",
            color: "#FF0000"
        },
        "gas": {
            title: "Gaskosten",
            color: "#00FF00"
        },
        "wasser": {
            title: "Wasserkosten",
            color: "#0000FF"
        },
        "gesamt": {
            title: "Gesamtkosten",
            color: "#FFFFFF"
        }
    };

    if (rdbStrom.checked) {

        dataArraysNeeded.push('strom');

    }

    if (rdbGas.checked) {

        dataArraysNeeded.push('gas');
    }

    if (rdbWasser.checked) {

        dataArraysNeeded.push('wasser');
    }

    if (rdbGesamt.checked) {

        dataArraysNeeded.push('gesamt');

    }

    // From here we have an array of labels (ex: ["wasser","gesamt"])
    // We now want to get the data array for each of these labels, here is how it's done

    for (let i = 0; i < dataArraysNeeded.length; i++) {
        dataArraysNeededAsPromises.push(getDataArray(dataArraysNeeded[i]));
    }

    // This will execute all the promises AND WAIT the end of the slowest promise
    return Promise.all(dataArraysNeededAsPromises).then((sets) => {

        let currentLabel = "";

        // sets[0] equals getDataArray("wasser") for example
        for (let j = 0; j < sets.length; j++) {

            currentLabel = dataArrayLabel[j]; // "wasser"

            dataset.push( {

                label: designParams[currentLabel]["title"],
                data: sets[j],
                borderColor: designParams[currentLabel]["color"],
                borderWidth: 1

            });

        }

        return dataset; // Array of objects {label, data, borderColor, borderWidth}

    });

}

有关Promise.all的工作原理,请参见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all


您的主函数 createGraph ,该函数调用createDatasets(您可以看到如何消耗返回承诺的函数的结果)

function createGraph() {
    // Create Canvas if not already created
    if (document.getElementById('datacanvas') == null) {
        var canvas = document.createElement('canvas');
        canvas.setAttribute("id", "datacanvas")
        var datadiv = document.getElementById("datadiv");
        datadiv.appendChild(canvas);
        var ctx = canvas.getContext("2d");
    }
    else {
        var canvas = document.getElementById('datacanvas')
        var ctx = canvas.getContext("2d");
    }

    var labls = ["Januar", "Februar", "März", "April", "Mai", "Juni",
        "Juli", "August", "September", "Oktober", "November", "Dezember"];


    // Here you instanciate your promise of Dataset, which IS NOT synchronous
    var datasetPromise = createDatasets();

    // So you need to specifiy a callback, executed on promise completion
    return datasetPromise.then((yourDatasetReadyToBeUsed) => {

        var chart = new Chart(ctx, {
            type: 'line',
            data: {
                labels: labls,
                datasets: yourDatasetReadyToBeUsed
            },
            options: {
                scales: {
                    yAxes: [{
                        ticks: {
                            beginAtZero: true
                        }
                    }]
                }
            }
        });

        return 'completed !';
    });

}

我会让您找到最后一个,因为它与这两个函数非常相似(getDataArray在读取文件时也需要返回Promise)! 对您来说更清楚吗?