Steve Steve - 3 months ago 11
Node.js Question

Getting array values from multidimensional array in JavaScript

I'm in need of some minor assistance. I'm having trouble getting an array (larray3) populated with two other array objects (larray1 and larray2) to pass both from data.js into the subsequent model.js and view.js. Data.js correctly builds the multidimensional array however when the results are received in model.js/view.js I only receive the results for larray1. Because only the first values come thru I cannot tell if both larray1 and larray2 are actually passing thru. Can someone please tell me how I should alter my syntax in either model.js or view.js to access both array values or what else I could change? Thank you in advance.

data.js.

function getCountries(done) {
var sqlite3 = require('sqlite3').verbose();
var file = 'db/locations.sqlite3';
var db = new sqlite3.Database(file);
var larray1 = [];
var larray2 = [];
var larray3 = [];

db.all('SELECT * FROM Country', function(err, rows) {
// This code only gets called when the database returns with a response.
rows.forEach(function(row) {
larray1.push(row.CountryName);
larray2.push(row.CountryCode);
})
larray3.push(larray1);
larray3.push(larray2);
return done(larray3[0], larray3[1]);
});
db.close();
}


model.js

function Countries(done) {
//Pull location values from data
return getCountries(done);
}


view.js

function viewCountries() {

var viewCou = Countries(function(results) {
// Code only gets triggered when Countries() calls return done(...);
var container = document.getElementById('country-select');
var fragment = document.createDocumentFragment();

results.forEach(function(loc, index) {
var opt = document.createElement('option');
opt.innerHTML = loc;
opt.value = loc;
fragment.appendChild(opt);
});
container.appendChild(fragment);
})
}

Answer

In data.js you send two arguments to the done callback:

return done(larray3[0], larray3[1]);

This done function is passed through in your model.js:

return getCountries(done);

And that done is passed in from view.js:

Countries(function(results) { // ...

So it is this anonymous function (function(results) {...}) that is called in data.js. But notice that this function only has one parameter, so you're doing nothing with the second argument that data.js sends. result gets the value of larray3[0], but larray3[1] is not captured anywhere.

You could solve this in different ways. Personally, I think the design with two arrays is wrong from the start. I would not separate data that belongs in pairs (name and code) into two different arrays.

Instead make an array of objects, and pass that single array around:

In data.js:

rows.forEach(function(row) {
    larray1.push({
        name: row.CountryName,
        code: row.CountryCode
    });
})
return done(larray1);

In view.js:

    opt.textContent = loc.name;
    opt.value = loc.code;

Side-note: .textContent is preferred over .innerHTML when assigning plain text.