0

I display a list, each item includes an array of ids that reference other documents (mongodb). When the user clicks on an item I want to populate the array with the actual documents (= replacing the ids with the corresponding object).

My problem is that the data is not applied to the correct place in the array once the requests finish. Probably the index that I hand over in the callback function is increased as the for loop marches on. By the time the request is ready, the for loop likely already finished so the result gets attached to the end of the array instead of its original position. I tried deep copying the index with angular.copy() although I believe that should not be necessary. I am not even sure if int is an object or a flat datatype, a small Google research yielded no clear answer to that.

I was able to re-create the problem in a plunkr.

I encountered a similar problem before but was able to work around it but this time I am not sure how to deal with this problem. Any hints?

1
  • Create a helper function that passes in 'i', and have the helper function call the timeout. Then the index will be saved. Commented Mar 18, 2014 at 3:33

2 Answers 2

1

You need to properly capture i for the current iteration by passing it into fetchSubItem()...

for( var i=0; i < item.subItems.length; i++ ) {
    // in the real world app fetchSubitem does an http api call
    fetchSubItem( item.subItems[i], i, function(result, i){
      // this happens long after the for loop and all finished
      item.subItems[i] = result;
    });
}

// ....

function fetchSubItem ( id, j, callback ) {
    var found = false
    for( var i=0; i < sideList.length; i++ ) {
      if ( sideList[i].id == id ) {
        found = true;
        $timeout( function(){ callback( sideList[i], j ); }, 1000 ); // to simulate asynchronicity
        break;
      }
    }
    if ( !found ) callback( "SubItem "+id+" not found.", j );
}

Plunker: http://plnkr.co/edit/8qTNUwjyWYrokc1bTXLI?p=preview

Sign up to request clarification or add additional context in comments.

Comments

0

The asynchronous call will assume the value of 'i' at the time it is invoked. Because of that you need to write a helper function to save the value of i. Something like this should work.

function fetchSubItem ( id, callback ) {
    function helper(i) {
        $timeout( function(){ callback( sideList[i] ); }, 1000 ); // to simulate asynchronicity
    }

    var found = false

    for( var i=0; i < sideList.length; i++ ) {
        if ( sideList[i].id == id ) {
            found = true;
            helper(i);
            break;
        }
    }
    if ( !found ) callback( "SubItem "+id+" not found." );
}

1 Comment

I think this solution should be somewhat equivalent to Anthony's solution. In the plunkr it did not work for some reason though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.