3

With the following code being asynchronous, it is my belief that the lifespan of the 'recipeData' array is not long enough to outlast the asynchronous callbacks, so I made a copy of the data in a global array, but I am still receiving the same error "TypeError: Cannot read property '_id' of undefined". Here is the code:

var tempArray;

function getAllRecipes( db, callback )
{
    query( db, {}, 'recipes', function( err, recipeData )
    {
        tempArray = recipeData.slice();

        if( err || !tempArray.length )
            callback( err );
        else
        {
            var taskArr = [];

            for( var i=0; i < tempArray.length; i++ )
            {               
                taskArr.push( function( iCallback )
                {
                    getRecipeNotes( db, tempArray[ i ]._id, function( err2, noteData )
                    {
                        if( err2 )
                            iCallback( err2 );

                        tempArray[ i ].notes = noteData;
                        iCallback();
                    });
                });
            }

            taskArr.push( function( err3 )
            {
                callback( err3, tempArray );
            });

            async.parallel( taskArr );
        }
    });
}

The error is occurring on the call to 'getRecipeNotes'.

Can someone please help me work out where I am going wrong?

Thank you.

MikeO
  • 391
  • 4
  • 17
  • 2
    [JavaScript closure inside loops – simple practical example](https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – Because `getRecipeNotes()` is asynchronous, the `for` loop is able to continue to modify `i` (with `i++`) before any of the callbacks are invoked. By the time they are, `i === tempArray.length`, the condition ending the loop. Using a closure, you can give each callback its own `i` to work with and remember each value from the loop. – Jonathan Lonowski Feb 27 '16 at 17:56
  • 1
    Oh wow that was so obvious now you have pointed it out – MikeO Feb 27 '16 at 17:58
  • 2
    Another option is to use [`let i`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#let_in_loops) in place of `var i`. Though, it's a newer feature (standardized by ES6, published last year) and has some limitations of [browser support](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#Browser_compatibility). – Jonathan Lonowski Feb 27 '16 at 18:01
  • 1
    let is not supported in Node.js, but it would work with a closure. I'll check and post the answer if it does work. Thank you for your help – MikeO Feb 27 '16 at 18:13
  • 2
    `let` [is supported by](https://nodejs.org/en/docs/es6/#which-features-ship-with-node-js-by-default-no-runtime-flag-required) Node 4.x and later, provided you [`'use strict';`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) as well (that's a temporary limitation currently imposed by V8). If you're using a lower version (`0.12.x`, etc.), the `--harmony` command-line flag may enable it. – Jonathan Lonowski Feb 27 '16 at 18:14
  • Yeah you're correct. Do you want to post it as an 'answer' on here instead of a comment, then I can mark it as correct? Thank you for your help – MikeO Feb 27 '16 at 18:20

1 Answers1

0

Another option is to use let i in place of var i. Though, it's a newer feature (standardized by ES6, published last year) and has some limitations of browser support. – Jonathan Lonowski 2 days ago

let is supported by Node 4.x and later, provided you 'use strict'; as well (that's a temporary limitation currently imposed by V8). If you're using a lower version (0.12.x, etc.), the --harmony command-line flag may enable it. – Jonathan Lonowski 2 days ago

MikeO
  • 391
  • 4
  • 17