ThePainfull
ThePainfull

Reputation: 125

How to pass variable to ajax.done() inside a loop?

I want to pass a variable to the .done() of my ajax call that happens inside a loop. Here is my original code :

    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js">    </script>
    </head> 

    <body>
        <div class="list">
            <div class="item" id="item1" data-user-id="1"></div>
            <div class="item" id="item2" data-user-id="2"></div>
            <div class="item" id="item3" data-user-id="3"></div>
            <div class="item" id="item4" data-user-id="4"></div>        
        </div>
        <script>           
            $('.list').children(".item").toArray().forEach(
                item => {            
                    $item = $(item)
                    $id = $item.data("userId")
                    $itemID = $item.attr('id')
                    $.ajax({
                        url: "https://jsonplaceholder.typicode.com/users",
                        data: { "id": $id },                    
                    }).done(res => {    
                        console.log($itemID)
                    });
                }
            );         
        </script>    
    </body>   
    item4
    item4
    item4
    item4

when I expected to see (in any order):

    item1
    item2
    item3
    item4

I found Passing variables to $.ajax().done() but neither of the 2 solutions worked :

the first one using immediately invoked function expression:

    .done(
        ((result) => {                        
            console.log(result)
            console.log($itemID)
        })(res)
    );
    ReferenceError: res is not defined

the second one using a custom ajax parameter :

    $.ajax({
        url: "https://jsonplaceholder.typicode.com/users",
        data: { "id": $id },
        custom: $itemID   
        // same results with custom: { customID: $itemID }             
    }).done(res => {                        
        console.log(res)
        console.log(this.cutsom)
        // same output with console.log($itemID)
        //                  console.log(this.$itemID)
    });
    item4
    undefined
    item4
    undefined
    item4
    undefined
    item4
    undefined

I found other solutions that did not work either (mostly using the deprecated success property). If I missed an obvious answer, I'm sorry, I tried my best.

Upvotes: 0

Views: 204

Answers (2)

Mauricio Sipmann
Mauricio Sipmann

Reputation: 475

The best way to code something like you want, is to put your .ajax method inside a function like the following. That way, you'll define a scope to the variables.

function req($id, $itemID) {
  $.ajax({
      url: "https://jsonplaceholder.typicode.com/users",
      data: { "id": $id },                    
  }).done(res => {    
      console.log($itemID)
  });
}

$('.list').children(".item").toArray().forEach(
    item => {            
        $item = $(item)
        $id = $item.data("userId")
        $itemID = $item.attr('id')
        req($id, $itemID);
    }
); 
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="list">
  <div class="item" id="item1" data-user-id="1"></div>
  <div class="item" id="item2" data-user-id="2"></div>
  <div class="item" id="item3" data-user-id="3"></div>
  <div class="item" id="item4" data-user-id="4"></div>        
</div>

Upvotes: 0

Lapskaus
Lapskaus

Reputation: 1721

Looks like a scope problem. You need to limit the scope of $item, $id and $itemId to your foreach function.

var $item = $(item);
var $id = $item.data("userId");
var $itemID = $item.attr('id');

Otherwise the last call of $itemID = ... holds your last id by the time your async ajax function is finished

Upvotes: 1

Related Questions