0

I'm pulling my hair out trying to understand javascript closures. I'm looking closely at this example. My actual code is in node.js but I don't think that's a major issue (except for error codes..)

Here's my slimmed down code:

var jsonsymbols = {
    "id5": "WFC",
    "id4": "AMZN",
    "id3": "BABA",
    "id2": "YHOO",
    "id1": "GOOG",
    "id0": "AAPL"
};
// assume an unknown number of stock symbols.. 

var count = 0;
var outputPrices = {};
for (key in jsonsymbols) {
    outputPrices['newid' + count]['price'] = get_price(jsonsymbols[key], count, function() {
        console.log("  Dummy function"); // callback function is used when looking up only one stock.
    });
    count++;
}
console.log("\ncount = " + count);
console.log("\noutput = " + JSON.stringify(outputPrices));

function get_price(symbol, countindex, callback) {
    setInterval(function() {
        // do nothing... The actual function makes a http call to another server 
        // and does stock price lookup.  We can only look up one stock at a time, 
        // hence the repeated calls.
    }, 1000);
    return 124.12;
    callback();
};

(hmmm. I'm new to this snippet stuff. I've also created a jsfiddle ) Current error code is Uncaught TypeError: Cannot set property 'price' of undefined I'm obviously missing something stupid. Is there any way to have my cake and drink beer too? I'm learning how this asynchronous stuff works, unfortunately I have a very difficult time beginning the learning process in pure abstract concepts. I need a concrete example to start, and from that I can extrapolate back to the abstract.

Anybody been here before? Why doesn't this work? thx.

Community
  • 1
  • 1
zipzit
  • 3,778
  • 4
  • 35
  • 63
  • `outputPrices['newid' + count]` has to exist as an object before setting `price`. – elclanrs Mar 17 '15 at 03:37
  • You are missing a `)` at the end of `console.log("\noutput = " + JSON.stringify(outputPrices));` – Arun P Johny Mar 17 '15 at 03:37
  • http://jsfiddle.net/arunpjohny/772d7aza/3/ – Arun P Johny Mar 17 '15 at 03:38
  • Yup, I found that a few minutes ago... fixed and updated the entire document and jsfiddle. Note the new error code... that matches what I see in my large project in node. – zipzit Mar 17 '15 at 03:38
  • you are calling `callback()` after the return so that won't get executed – Arun P Johny Mar 17 '15 at 03:39
  • Arun, pls post your notes as an answer so I can accept them? Also what's up with the line of code `outputPrices['newid' + count] = outputPrices['newid' + count] || {}` what does `|| {}` do? – zipzit Mar 17 '15 at 03:46
  • The solution is not yet complete... – Arun P Johny Mar 17 '15 at 04:00
  • http://jsfiddle.net/arunpjohny/772d7aza/4/ – Arun P Johny Mar 17 '15 at 04:05
  • frick: `Object.keys(jsonsymbols).length`, `(function(key, count){` followed by `})(key, count)`, and the `|| {}` trick..... I'm blown away. How do you know this stuff? What is the name of the (function(key,count)... technique? Is that function scope binding? In my best Wayne's World, I'm on my knees to you "I'm not worthy, I'm not worthy..." – zipzit Mar 17 '15 at 04:17
  • This is not a closure problem. It's a problem of not understanding how asynchronous code works. – slebetman Mar 17 '15 at 04:22
  • You are right. I understand the problem, not a robust viable solution to accommodate that behavior that sticks in my head. I can't obtain a stock price without looking it up on a server somewhere. I'd like to pause and wait for the result before moving forward. What's your best recommendation for how to approach the issue? I can't nest callbacks in a variable loop very easily? (or can I?) Link for best practices? – zipzit Mar 17 '15 at 04:29
  • So what do you guys think of using the nodejs tool node-async ... its a hack, but a hack published in npm. ASYNC.EACH OR ASYNC.PARALLEL should do it. I'm just not clear on how to perform a 'wait' operation for a slow asynchronous function that is called from within a loop a variable # of times. I'm doing this on a node server, not in a client. – zipzit Mar 17 '15 at 04:57
  • The node-async functions are not "hacks". They're good, best-practice design patterns for asynchronous control flow implemented as a reusable library. You may check out one of my old answers on SO (written before async.js) to see how such functions work: http://stackoverflow.com/questions/4631774/coordinating-parallel-execution-in-node-js/4631909#4631909 – slebetman Mar 17 '15 at 05:22
  • Check out this other answer, based on my answer in the link above, for how to fetch things in sequence, one at a time: http://stackoverflow.com/questions/12775021/callback-in-javascript-loop-causes-issue/12775854#12775854 – slebetman Mar 17 '15 at 05:23
  • Though these days I'd recommend using async.js instead of rolling up your own control-flow code. Not least because it's easier to google for solutions and code samples because lots of people use it. – slebetman Mar 17 '15 at 05:24
  • Er.. so what's the best way to pass a value from an asynchronous function call to a JSON variable? I don't dare use a global variable. I'm told to use a callback function and not to use a return value. Its not clear to me on exactly how to push a value onto an object. Global I can do, but that's fraught with danger. do I pass in a reference to a variable in the function call? – zipzit Mar 17 '15 at 05:30

0 Answers0