0

I am using this query to select all records from the products table and I want to store them inside an object variable which later I can use it for other purposes, so I tried this

 var SelectQuery = "Select * FROM `products`";
 var ProductDetails = {};
 conn.query(SelectQuery, function (err, result) {
     if(err) {
        console.log(err);
      } else {
        ProductDetails = result;
      }
 });

 console.log(ProductDetails);

But in Console I get this {}.

Shadow
  • 33,525
  • 10
  • 51
  • 64
m.o
  • 113
  • 1
  • 2
  • 8
  • 1
    Wouldn't you need to move your console.log(ProductDetails) into the else block above for this to display the results? – Ryan Wilson Mar 04 '18 at 22:16
  • Ryan Wilson is correct-- you are looking at the code as if it executes line by line, but that is not quite correct-- the function passed as the second argument to `query` is a callback, and will only execute after the query has completed. Meanwhile the code outside that will continue to run in order. So what is happening in your code above is that you are console logging `ProductDetails` before the `result` has actually been assigned to it. – Alexander Nied Mar 04 '18 at 22:18
  • I get the result but I need a way to access to result's records out of the function block – m.o Mar 04 '18 at 22:20
  • Well, you either need to put whatever behavior you need into a function that is called from within the callback, or to leverage a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), or leverage [`async`/`await`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) -- but note that that is not natively available in all browsers. – Alexander Nied Mar 04 '18 at 22:22
  • @AlexanderNied I know this I can have the result's records in the console if I place the console.log(result) inside the function, but I need the result's records outside the function – m.o Mar 04 '18 at 22:23
  • 1
    @a.Sahel -- see my above comment. When dealing with asynchronous code, you have a pretty well defined tool set for handling it-- [callback pattern](https://developer.mozilla.org/en-US/docs/Glossary/Callback_function), [Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), or [`async`/`await`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function). Maybe somebody else can think of another approach, but I think this about covers it. – Alexander Nied Mar 04 '18 at 22:26
  • Can you provide an example – m.o Mar 04 '18 at 22:30

1 Answers1

0

(Thanks to user jfriend00 for pointing out a major oversight in my original answer)

If conn.query is returning a promise then you could make this work in the manner you are describing by using async/await:

async function getProducts() {
     var SelectQuery = "Select * FROM `products`";
     var ProductDetails = {};
     await conn.query(SelectQuery, function(err, result) {
         if (err) {
             console.log(err);
         } else {
             ProductDetails = result;
         }
     });    

    console.log(ProductDetails);
}

But note this only works if your conn.query returns a promise. Also, it is a newer ES feature, so you may need to transpile it depending on your node version. Also, note that the function this takes place in will need to be wrapped with async.

Otherwise, the other candidates to leverage for handling asynchronicity are callback functions and Promises.

If conn.query does not return a promise, you could write your own query implementation that would return a promise so you could leverage async/await:

function asyncQuery(sqlQuery) {
    return new Promise((resolve, reject) => {
        conn.query(SelectQuery, function(err, result) {
             if (err) {
                 reject(err);
             } else {
                 resolve(result);
             }
         })
    })
}

Then the original function could be rewritten as:

async function getProducts() {
    var SelectQuery = "Select * FROM `products`";
    var ProductDetails = await asyncQuery(SelectQuery);
    console.log(ProductDetails);
}
Alexander Nied
  • 12,804
  • 4
  • 25
  • 45
  • Do you have any evidence that `conn.query()` returns a promise, particularly when passed a callback? I rather doubt it and thus `await` would not wait for the async operation to be done. `await` only waits on a promise, nothing else. – jfriend00 Mar 04 '18 at 23:36
  • @jfriend00 -- _excellent_ point. I've grown accustomed to asynchronous functions returning promises as a matter of course, but I am absolutely just presuming that this is the case. I'll edit the answer accordingly. Thanks for calling that out. – Alexander Nied Mar 05 '18 at 04:34
  • @Alexander Nied it gives me this error in the console `Promise { }` – m.o Mar 05 '18 at 08:47