meternx01
meternx01

Reputation: 11

Scoping with Node.js and the MySQL query function callback

I am trying to write a JavaScript object as part of a shopping assignment using Node and MySQL. I wanted to test myself by making it more OOP than functional programming. I am creating a constructor for a Transaction object with the properties for item selected, quantity wanted, and total cost. Also, would be the methods for displaying items, selecting items, and purchasing items.

Starting out, I wanted to also have an array of unique itemIDs that would be the verification that a user chose a valid product. I am having a scoping problem where this.ids[] is undefined if defined in the object's scope. My solution below would be defining it locally and passing that array as arguments to avoid scoping. This solution would also wouldn't allow me to access the Transaction object's scoped variables.

this.listProducts = function(connection) {
    connection.query("SELECT * FROM products WHERE stock_quantity>0", function(err,res) {
        if (err) throw err;
        this.ids = [];
        for (var i = 0; i < res.length; i++) {
            this.ids.push(res[i].item_id);
            console.log(res[i].item_id + " " + res[i].product_name + " " + res[i].price);
        }
        // res.forEach(function (element) {
        //  console.log("this.ids=",this.ids);
        //  this.ids.push(element.item_id);
        //  console.log(element.item_id + " " + element.product_name + " " + element.price);
        // });
        connection.end();
        console.log(this.totalCost, this.ids);
    });
};

I tried to

         ....
         console.log(this.totalCost, this.ids);
    });
}.call(this);

I get TypeError: connection.query(...).call is not a function

Do I have my scoping all messed up? How can I fix the scoping issue so I can access the "Transaction" object's scope?

Let me know if my question is not phrased coherently...

Upvotes: 1

Views: 463

Answers (1)

Shyam Babu
Shyam Babu

Reputation: 1079

I believe there are two options here you can use

the new arrow function which binds this to wherever it was defined.

this.listProducts = function(connection) {
    var that = this;
    connection.query("SELECT * FROM products WHERE stock_quantity>0", 
     //use arrow instead of anonymous function
     (err,res) => {
        if (err) throw err;
        this.ids = [];
        for (var i = 0; i < res.length; i++) {
            this.ids.push(res[i].item_id);
            console.log(res[i].item_id + " " + res[i].product_name + " " + res[i].price);
        }
        connection.end();
        console.log(this.totalCost, this.ids);
    });
}

or store the this reference like

this.listProducts = function(connection) {
    var that = this;
    connection.query("SELECT * FROM products WHERE stock_quantity>0", function(err,res) {
        if (err) throw err;
        that.ids = [];
        for (var i = 0; i < res.length; i++) {
            that.ids.push(res[i].item_id);
            console.log(res[i].item_id + " " + res[i].product_name + " " + res[i].price);
        }
        connection.end();
        console.log(that.totalCost, that.ids);
    });
}

Upvotes: 1

Related Questions