Electron / JS Подождите, пока переменная получит данные из другой функции - PullRequest
0 голосов
/ 15 марта 2019

В настоящее время я учусь использовать Электрон для университетского проекта. Я пытаюсь прочитать данные из файла .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 голосов
/ 15 марта 2019

Это из-за проблемы асинхронности, вы используете 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}

    });

}

См. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all для получения подробной информации о том, как работает 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, когда он читает файл)! Вам это понятнее?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...