Search code examples
javascriptnode.jsfunctionscopenode-mysql

Writing to an array in a higher scope, from within a query's anonymous function


I need to return a value from a function, which gets its information from a query. I'm having some trouble passing information from the query's anonymous function to the container function.

I tried creating an array in a higher scope (the container function) and having the query function write to the array per result, but that didn't seem to work. I also tried passing the array into the query's anonymous function. That did not appear to work either.


Here's my function (executed within Node):

function retrieveSales(connection,timeFrame) {

    var sales = new Array();

    connection.query('select * from sales_entries where date BETWEEN ? AND ?',
    timeFrame,

    function (err, rows, fields, sales) {

        if (err) return callback(new Error('Failed to connect'), null);

        connection.end();

        for (x = 0; x < rows.length; x++) {
            sales.push(rows[x]);
        }

    });

    console.log('Sales Returned: ' + JSON.stringify(sales, null, 4));

    return sales;

}

which result in 'cannot call method 'push' of undefined.

How should I properly write to the sales array so that I can return it with retrieveSales()?


Solution

  • You are dealing with JavaScript's beautiful asynchronous-ness-icity. You are are trying to return out of an asynchronous method. Try to brush up on how asynchronous programming works, and it'll make your life much, much easier; it isn't very hard, just different. Check out this code sample, hopefully it can get you up and going.

    // use this as your callback to handle the results from connection.query()
    function sales_cb(rows) {
      var sales = [];
      for (x = 0; x < rows.length; x++) {
        sales.push(rows[x]);
      }
      console.log('Sales Returned: ' + JSON.stringify(sales, null, 4));
    }
    
    function retrieveSales(connection, timeFrame) {
      // connection.query() is asynchronous - interact with it accordingly
      connection.query('select * from sales_entries where date BETWEEN ? AND ?', timeFrame,
        function (err, rows, fields, sales) {
          if (err) {
            callback(new Error('Failed to connect'), null);
          } else {
            // invoke sales_cb(sales) once the for loop is done
            sales_cb(rows);
          }
        });
    }
    

    Let me know if this helps :)