I need to recover in towerjs (with mongodb store) quote stock from all stock in all trades of one user. This code don't work, the while loop does not stop, but I do not understand why
App.Trade.where(userId: @currentUser.get('id')).order("date", "desc").all (error, trades) ->
idst = {}
i = 0
len = trades.length
while i < len
trade = trades[i]
idst[trade.get('stockTicker')] = 1 if trade.get('stockId') and not idst[trade.get('stockId')]
i++
App.Stock.where({ticker: {$in: Object.keys(idst)}}).all (error, stocks) ->
map = {}
mapQuote = {}
i = 0
len = stocks.length
while i < len
stock = stocks[i]
map[stock.get('ticker')] = stock
App.QuoteStock.where(ticker: stock.get('ticker')).order("createdAt", "desc").limit(1).first (error, quoteStock) ->
mapQuote[stock.get('ticker')] = quoteStock
i++
i = 0
len = trades.length
while i < len
trade = trades[i]
trade.stock = map[trade.get('stockTicker')]
trade.quoteStock = mapQuote[trade.get('stockTicker')]
i++
_this.trades = trades
It looks like there are a couple places where the problem might be occurring.
In the first while
loop, I'm not sure if you meant this:
idst[trade.get('stockTicker')] = 1 if trade.get('stockId') and not idst[trade.get('stockId')]
That last bit, idst[trade.get('stockId')]
is never set. But that doesn't interrupt the while loop, so probably not the issue.
The main thing is, because the second and third while
loop are inside the asynchronous App.Trade.where
function, they're not going to work correctly.
Also, the following will not work because the asynchronous code is called each iteration:
while i < len
stock = stocks[i]
map[stock.get('ticker')] = stock
App.QuoteStock.where(ticker: stock.get('ticker')).order("createdAt", "desc").limit(1).first (error, quoteStock) ->
mapQuote[stock.get('ticker')] = quoteStock
i++
Instead you need to use an asynchronous loop: https://github.com/caolan/async. You can do that like this:
async = require('async')
stocksIterator = (stock, next) ->
map[stock.get('ticker')] = stock
App.QuoteStock.where(ticker: stock.get('ticker')).order("createdAt", "desc").limit(1).first (error, quoteStock) ->
mapQuote[stock.get('ticker')] = quoteStock
next()
async.forEachSeries stocks, stocksIterator, (error) ->
tradesIterator = (trade, next) ->
trade.stock = map[trade.get('stockTicker')]
trade.quoteStock = mapQuote[trade.get('stockTicker')]
next()
async.forEachSeries trades, tradesIterator, (error) ->
_this.trades = trades
Also, if I were you I would put each of these iterators into separate functions, or use different index variables (i
, j
, k
for example). It makes mentally dealing with the async nature of this easier.
Let me know if that works. Cheers.
oh my god, your code looks terrible... ( so many i++
, i < length
, in nested scopes) please... don't write code in that way, smells too bad. nested loops leads to your code too hard to read, especially there are shadow variables.
so, the problem you met is "Shadow variables", which looks like:
some_var = "I am normal"
shadow_it = ->
some_var = "this is the shadow"
# blabla
I suggest you improve the implementation of your algorithm, avoid using shadow variables.