3

I've been working on getting a function to output an array but nothing I do seems to let me return an array or access the array outside of the function.

I'm using node.js and mysql and am trying to pull row data, modify it, and then put it into an array. I seem to be able to put it into an array because within the function, I can console.log the variable I set the array to and I get what I'm looking for. But I can't get it out of the array. At first I was using forEach() but have switched to using map().

Currently this is where I'm at:

let sql = "SELECT invoice FROM subscriptions";
myFunction = () => {
  con.query(sql, (err, rows) => {
    if (err) throw err;
    var newArray = rows.map((row) => {
      return row.invoice;
    })
    console.log(newArray)
  })
}
myFunction();

If I change console.log(newArray) to return newArray there doesn't seem to be any evidence that this gives me what I'm looking for.

I've also tried to define variable outside of the function and then set the newArray to the variable outside of the function:

let sql = "SELECT invoice FROM subscriptions";
myArray = []
myFunction = () => {
  con.query(sql, (err, rows) => {
    if (err) throw err;
    var newArray = rows.map((row) => {
      return row.invoice;
    })
    myArray = newArray
  })
}
myFunction();
console.log(myArray)

This only results in []

In this code, rows is returning the invoice numbers from the subscriptions table. The result is:

[ '23480-13',
  '23354-14',
  '23728-14',
  '23614-16',
  '16132-14',
  ... more results ]

So console.log within the function seems to be correct. But if I try to return newArray, as far as I can tell, the function is not returning anything.

This certainly seems like a simple problem but I've been stuck for hours. How can I create a function that will return an array I can use in a new function?

worldwidejamie
  • 235
  • 1
  • 3
  • 15
  • Presumably that's `let sql` instead of `et sql`. – tadman May 03 '19 at 17:41
  • I suppose that is addresses the same issue but I also don't know if this would have answered my question would I have come across it. So I guess the issue is the same, what I was looking for regarding how to solve the problem wasn't something I quite understood. That said, knowing about that article is going to help a lot moving forward. – worldwidejamie May 03 '19 at 17:54

2 Answers2

3

This is callback-driven code so you must supply a callback function to chain properly:

function myFunction(cb) {
  // Supply your query directly to query() so you don't accidentally
  // send the wrong query by using an incorrect or undefined variable.
  con.query("SELECT invoice FROM subscriptions", (err, rows) => {
    // NOTE: This function runs at some point in the unspecified future,
    //       but you can request a callback when it's done.
    if (err) throw err;

    let newArray = rows.map((row) => {
      return row.invoice;
    })

    cb(newArray);
  })
}

myFunction(myArray => {
  console.log(myArray);
});

Without proper sequencing nothing in your JavaScript code will run at the right time.

Note that using Promises helps simplify this sort of code dramatically since you can do basically this:

let myArray = await con.query(...);
tadman
  • 208,517
  • 23
  • 234
  • 262
1

You can use a callback like @tadman suggests, but I would suggest that you use a Promise. Using a Promise allows other functions to call this one using await.

Promise version:

function myFunction() {
  return new Promise(
    (resolve, reject) => {
      con.query("SELECT invoice FROM subscriptions", (err, rows) => {
        if (err) {
          reject(err);
        }

        resolve(rows.map(row => row.invoice));
      })
    }
  );
}

myFunction().then(myArray => {
  console.log(myArray);
});

If you are in another function then you can call myFunction using await:

async function getData() {
  myArray = await myFunction();
  console.log(myArray);
  return myArray;
}
Intervalia
  • 10,248
  • 2
  • 30
  • 60
  • Great example, but it's worth noting two things here. First, many libraries support both callback and promise methods of calling. Secondly you can often [`promisify`](http://bluebirdjs.com/docs/api/promise.promisify.html) a callback function to make it a promise instead. – tadman May 03 '19 at 19:07