Search code examples
javascriptcoffeescriptscopepromiselexical-scope

Lexical scoping in a for loop enclosing a promise?


I have an ids object, which maps id strings to product objects.

for id of ids
  product = ids[id]
  console.log product # Prints out something different each loop. :)
  Product.create(product).then ->
    console.log product # Only prints out the last id each loop. :(

I'm using a library for database interactions, which exposes promises (indicated by the then function above). I'm trying to print out the product variable inside the then function, but I only seem to be getting the last id in ids, so it looks like it's a scoping issue. How can I scope the product variable properly so that it prints out a different product in the then function each loop?


Solution

  • @false did find the right duplicate describing your issue. Indeed, you've got a scoping issue where product is non-local to the loop body, and you get the last item only from your asynchronous callbacks.

    How can I scope the product variable properly so that it prints out a different product in the then callback?

    In idiomatic coffeescript, you will use the do notation for the IEFE in the loop:

    for id of ids
      do (product = ids[id]) ->
        console.log product
        Product.create(product).then ->
          console.log product
    

    Or, drawing the property value directly from the of-loop:

    for id, product of ids
      do (product) ->
        …