-1

I have a client-side web-application that takes a csv-file, parses it into various data types, searches for something specific, and displays a table with the answer on the screen. The search function returning a null string. This occurs because its search parameter, returned by a callback function and put into lib, returns null.

I'm fairly certain this is a callback issue, but I've messed around with the order so much I'm not sure what goes where anymore in my html...A second set of eyes would be appreciated.

The desired series of events

  1. fileToArray() gives us an array
  2. search() looks in the array for its specified item and returns a csv-format string containing what it found
  3. displayTable takes that csv-format string and outputs it to the desired location

The Code

// jQuery call to fetch the client-side csv file - this works when called by itself.
const fileToArray = () => {
    console.log("fileToArray started.");
    $.get({
        url: CSV_LOCATION,
        dataType: "text",
        success: function (result) {
            console.log("splitting result by newline...");
            let csvLines = result.split("\n");
            console.log("split successful. generating array into retval ...");
            let retval = [];
            for (let i = 0; i < csvLines.length; i++) {
                // [0][0] is number [0][1] is class, [0][2] is unit, [0][3] is lesson
                retval[i] = csvLines[i].split(",");
            }
            console.log("success! Returning retval.");
            return retval;

            // callback(result);
            // return result;
        },
        failure: function (xhr, status, error) {
            console.log("ERROR: fileToString(): " + xhr + " ||| " + status + " ||| " + error);
            alert("ERROR: fileToString(): " + xhr + " ||| " + status + " ||| " + error);
        }
    })
};

// PRECONDITION: form is #search-params in index.js
//      > lib is the result of fileToArray()
// POSTCONDITION: result is a csv-format string to be passed to displayTable() in index.js
const search = (form, callback) => {
    console.log("search called...");
    // vvvvv The probable root of the problem vvvvv //
    let lib = callback;

    console.log(lib.length + " is lib's length.");

    let result = "";
    console.log("search nested for loop called...");
    for (let i = 0; i < lib.length; i++) {
        // check class
        console.log("checking class " + form.class.value + "...");
        if (lib[i][1] === form.class.value) {
            // check unit
            console.log("checking unit " + form.unit.value + "...");
            if (Number(lib[i][2]) === Number(form.unit.value)) {
                console.log("adding to result...");
                result += lib[i] + "\n";
            }
        }
    }
    console.log("search success! result: " + result.length + " characters");
    console.log(result);
    return result;
};
<!-- I'm almost 100% certain I've messed up the callback in this button,
but I still don't quite understand how... I've played with
displayTable(fileToArray(search(...))), but I don't quite know how it should go -->
<button class="btn btn-primary"
                onclick="displayTable(search(document.getElementById('search-params'), fileToArray), $('#card-display'))">
            Submit
</button>

What I've tried

I have looked to the following sites for inspiration (none have helped):

  1. JavaScript is Sexy
  2. JavaScript: Passing parameters to a callback function
  3. JavaScript Callback Functions
  4. Passing arguments to callback functions

In Summary

It's painfully obvious I still don't understand callbacks fully. Any help would be appreciated.

Jonathan
  • 104
  • 1
  • 10

2 Answers2

0

You could use async / await

const displayTable = async () => {
    let arrayFromFile = await fileToArray(); // fileToArray executes and assigns the returned value when it completes
    let searchedData = search(form, arrayFromFile);
    // Display the table
};
kapantzak
  • 11,610
  • 4
  • 39
  • 61
-1

Thanks to @kapantzak for the inspiration!! Turns out, I was using callbacks horribly bass-ackwards. According to this, the old-school async style is something akin to

doSomething(function(result) {
  doSomethingElse(result, function(newResult) {
    doThirdThing(newResult, function(finalResult) {
      console.log('Got the final result: ' + finalResult);
    }, failureCallback);
  }, failureCallback);
}, failureCallback);

So, the relevant code now looks like this:

const fileToArray = (callback) => {
    // console.log("fileToArray started.");
    $.get({
        url: CSV_LOCATION,
        dataType: "text",
        success: function (result) {
            let csvLines = result.split("\n");
            let retVal = [];
            for (let i = 0; i < csvLines.length; i++) {
                // [0][0] is number [0][1] is class, [0][2] is unit, [0][3] is lesson
                retVal[i] = csvLines[i].split(",");
            }
            callback(retVal);
        },
        failure: function (xhr, status, error) {
            console.log("ERROR: fileToString(): " + xhr + " ||| " + status + " ||| " + error);
            alert("ERROR: fileToString(): " + xhr + " ||| " + status + " ||| " + error);
        }
    })
};
// =======

const search = (form, lib, callback) => {
    let result = "";
    let formClass = form.class.value.toLowerCase();
    let formUnit  = form.unit.value.toLowerCase();
    let formLesson = form.lesson.value.toLowerCase();
    for (let i = 0; i < lib.length; i++) {
        // check class
        if (lib[i][1].toLowerCase() === formClass) {
            // check unit
            if (Number(lib[i][2].toLowerCase()) === Number(formUnit)) {
                result += lib[i] + "\n";
            }
        }
    }
    console.log(result);
    callback(result);
};
        <button class="btn btn-primary"
                onclick="fileToArray(function(result) {
                  search(document.getElementById('search-params'), result, function(newResult) {
                    displayTable(newResult, $('#card-display'));
                  });
                });">
            Submit
        </button>

This righted the wrongs and caused my search and display to function properly.

Jonathan
  • 104
  • 1
  • 10