0

I would like to make a program that can keep track of multiple stock objects and display basic information about them (IE: their price).

I have this code which can successfully retrieve the price of the stock:

function getStock(symbol, callback){
          var url = 'https://query.yahooapis.com/v1/public/yql';
    var data = encodeURIComponent("select * from yahoo.finance.quotes where symbol in ('" + symbol + "')");

    $.getJSON(url, 'q=' + data + "&format=json&diagnostics=true&env=http://datatables.org/alltables.env")
        .done(function (data) {
       result = data.query.results.quote.LastTradePriceOnly;
           callback(result);
        })
        .fail(function (jqxhr, textStatus, error) {
            var err = textStatus + ", " + error;
            console.log('Request failed: ' + err);
        });
}

getStock("goog", function(){alert(result)});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

I would like to be able to create a simple object that can keep track of a stock. However, I have problems with asynchrony and the JSON request. Here is my code with the "stock" object:

function getStock(symbol, callback) {
  var url = 'https://query.yahooapis.com/v1/public/yql';
  var data = encodeURIComponent("select * from yahoo.finance.quotes where symbol in ('" + symbol + "')");

  $.getJSON(url, 'q=' + data + "&format=json&diagnostics=true&env=http://datatables.org/alltables.env")
    .done(function(data) {
      result = data.query.results.quote.LastTradePriceOnly;
      callback(result);
    })
    .fail(function(jqxhr, textStatus, error) {
      var err = textStatus + ", " + error;
      console.log('Request failed: ' + err);
    });
}

function stock(symbol) {

  this.price = 0;

  getStock(symbol, function(result) { //this function is my callback
    console.log(result);
    this.price = result;
  });

  this.printPrice = function() {
    alert("The price is: " + this.price);
  }
}


var s = new stock("goog");
$("#button").click(function() {
  s.printPrice()
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="button">Print Price</button>

As you may notice, I tried using a callback which seems to be the appropriate solution to this problem (new to Javascript). However, it doesn't seem to actually be setting the class variable. In the console it does print the correct price, but it doesnt seem to change "this.price" (which is what I need it to do)

Any advice as to why this doesn't work, or how to create an "updateStockPrice()" method would be really helpful.

Maximilian Sun
  • 147
  • 1
  • 10
  • 1
    `this` inside your callback function no longer refers to `this` of `stock` function. See http://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-context-inside-a-callback. – Jasen Apr 14 '15 at 00:55

4 Answers4

1

I put together a jQuery plugin for this. Hope this can be helpful for someone

<!-- import jQuery and the plugin -->
<script src="bower_components/jquery/jquery.js"></script>
<script src="bower_components/jquery-stockquotes/dist/jquery.stockquotes.js"></script>
<link rel="stylesheet" type="text/css" href="bower_components/jquery-stockquotes/dist/jquery.stockquotes.css" />

<!-- the HTML integration -->
Twitter:  <span class="stock-quote" data-symbol="TWTR"></span>
Facebook: <span class="stock-quote" data-symbol="FB"></span>
Google:   <span class="stock-quote" data-symbol="GOOGL"></span>
Netflix:  <span class="stock-quote" data-symbol="NTFLX"></span>
Yahoo:    <span class="stock-quote" data-symbol="YHOO"></span>

<!-- the JS integration -->
<script>
$(document).on('ready', function () {
  $('.stock-quote').stockQuotes();
});
</script>

enter image description here

https://github.com/ajwhite/jquery-stockquotes

Atticus
  • 6,585
  • 10
  • 35
  • 57
0

The this you are calling on

s.printPrice()

is no longer in the same scope to be able to use

alert("The price is: " + this.price);

So add a reference to the initial this to further access its variable in your class:

var that = this;

function getStock(symbol, callback) {
  var url = 'https://query.yahooapis.com/v1/public/yql';
  var data = encodeURIComponent("select * from yahoo.finance.quotes where symbol in ('" + symbol + "')");

  $.getJSON(url, 'q=' + data + "&format=json&diagnostics=true&env=http://datatables.org/alltables.env")
    .done(function(data) {
      result = data.query.results.quote.LastTradePriceOnly;
      callback(result);
    })
    .fail(function(jqxhr, textStatus, error) {
      var err = textStatus + ", " + error;
      console.log('Request failed: ' + err);
    });
}

function stock(symbol) {

  var that = this;
  
  that.price = 0;

  getStock(symbol, function(result) { //this function is my callback
    console.log(result);
    console.log("1");
    that.price = result;
  });

  that.printPrice = function() {
    alert("The price is: " + that.price);
  }
}


var s = new stock("goog");
$("#button").click(function() {
  s.printPrice()
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="button">Print Price</button>
RobertoNovelo
  • 3,347
  • 3
  • 21
  • 32
  • Please explain your answer instead of simply posting revised code. This lets other users know what you've done/changed and offers a learning opportunity. – matcartmill Apr 14 '15 at 00:57
  • 1
    His initital explanation with "that" and scope was helpful I think. Thanks for the answer! – Maximilian Sun Apr 14 '15 at 01:02
0

I Just changed the var price to the top, to make it declared global for the functions. This way, they all share it and you´ll be able to print it.

Hope it´ll help you!!

   function getStock(symbol, callback) {
  var url = 'https://query.yahooapis.com/v1/public/yql';
  var price=0;
  var data = encodeURIComponent("select * from yahoo.finance.quotes where symbol in ('" + symbol + "')");

  $.getJSON(url, 'q=' + data + "&format=json&diagnostics=true&env=http://datatables.org/alltables.env")
    .done(function(data) {
      result = data.query.results.quote.LastTradePriceOnly;
      callback(result);
    })
    .fail(function(jqxhr, textStatus, error) {
      var err = textStatus + ", " + error;
      console.log('Request failed: ' + err);
    });
}

function stock(symbol) {


  getStock(symbol, function(result) { //this function is my callback
    console.log(result);
    price = result;
  });

  this.printPrice = function() {
    alert("The price is: " + price);
  }
}


var s = new stock("goog");
$("#button").click(function() {
  s.printPrice()
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="button">Print Price</button>

function getStock(symbol, callback) {
  var url = 'https://query.yahooapis.com/v1/public/yql';
  var data = encodeURIComponent("select * from yahoo.finance.quotes where symbol in ('" + symbol + "')");

  $.getJSON(url, 'q=' + data + "&format=json&diagnostics=true&env=http://datatables.org/alltables.env")
    .done(function(data) {
      result = data.query.results.quote.LastTradePriceOnly;
      callback(result);
    })
    .fail(function(jqxhr, textStatus, error) {
      var err = textStatus + ", " + error;
      console.log('Request failed: ' + err);
    });
}

function stock(symbol) {

  this.price = 0;

  getStock(symbol, function(result) { //this function is my callback
    console.log(result);
    this.price = result;
  });

  this.printPrice = function() {
    alert("The price is: " + this.price);
  }
}


var s = new stock("goog");
$("#button").click(function() {
  s.printPrice()
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="button">Print Price</button>
0

It is time to say hello to ES5 and bind method to set execution context. Stock.getStock now returns promise - after click ther will be executed query for the latest price of the stock.

function getStock(symbol, callback) {
    var url = 'https://query.yahooapis.com/v1/public/yql';
    var data = encodeURIComponent("select * from yahoo.finance.quotes where symbol in ('" + symbol + "')");

    $.getJSON(url, 'q=' + data + "&format=json&diagnostics=true&env=http://datatables.org/alltables.env")
        .done(function (data) {
        result = data.query.results.quote.LastTradePriceOnly;
        callback(result);
    })
        .fail(function (jqxhr, textStatus, error) {
        var err = textStatus + ", " + error;
        console.log('Request failed: ' + err);
    });
}

function Stock(symbol) {
    this.price = 0;

    this.getStock = function () {
        var dfd = jQuery.Deferred();
        getStock(symbol, function (result) {
            this.price = result;
            dfd.resolve(result);
        }.bind(this));
        return dfd.promise();
    }.bind(this);

    this.printPrice = function () {
        alert("The price is: " + this.price);
    }.bind(this);
}

var s = new Stock("goog");
$("#button").click(function () {
    s.getStock().then(s.printPrice).done();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="button">Print Price</button>
Krzysztof Safjanowski
  • 7,292
  • 3
  • 35
  • 47