1

I've been trying to understand Javascript closures, and thought I was onto something. I have managed to successfully return an iterated integer (generated by a for loop) within my inner function.

However, this function in question also takes a parameter generated by the function itself. Forgive my terminology - but it may be a callaback parameter (basically, the parameter's value is returned based on the function I send out).

There is more explanation of my problem below, but first of all, here is the code in question (with the closure working - [value] is a changing value of i for each iteration):

FB.api('/me/tagged?limit=100', function(response) {

for (var i=0; i<response.data.length; i++){

    var taggedId = response.data[i].id;
    var fromId = response.data[i].from.id;
    var fromName = response.data[i].from.name;

    var taggedQuery = new Parse.Query('tagged');
    taggedQuery.equalTo('taggedId',taggedId);
    taggedQuery.first({ //.first returns the first match (.find returns all)
        success: (function(value) {
            return function() {
            console.log(response.data[value]);
            }
        })(i),
        error: function(taggedRecError){
            console.log('error: '+taggedRecError.message);
        }
   });
} //for
});

So basically, in the above, I'm querying Facebook to get the user's tagged posts. I use a for loop to iterate through each result.

I then use Parse.js to query whether I have a record saved for this tagged object.

I want my code to recognise whether or not I do (have a saved object). In Parse I would usually do this using something like the following:

taggedQuery.first({ //.first returns the first match (.find returns all)
        success: function(value) {
                if(value){
                   //do nothing
                 }
                else {
                   //do something - e.g. save to Parse data store
                }

        }
});

So, as you can see, I use the existence of a returned paramater (value) in order to decide what to do next.

However, in the first code block, you can see that in order to get the closure working I have to pass a parameter ('(i)') directly into the success function in order to get the appropriate value of i for use within the function. However, this then distorts the result we get from Parse - i.e. the returned object comes from me passing in a parameter - not from Parse returning one based on my data store

I seem to be in a catch 22: pass in a parameter manually to get successful closure (but then lose the returned paramater from the Parse call), or pass in no parameter to ensure Parse returns the correct response based on my data stores (but then have the wrong value of i within said function: i.e. - no closure).

I hope that's clear. If not please let me know. Any help appreciated.

Josh Oldham
  • 192
  • 1
  • 1
  • 14

2 Answers2

2

You could use [].forEach to simplify it a lot:

FB.api('/me/tagged?limit=100', function(response) {
    response.data.forEach(function(value, i) {
        var taggedId = value.id;
        var fromId = value.from.id;
        var fromName = value.from.name;
        var taggedQuery = new Parse.Query('tagged');
        taggedQuery.equalTo('taggedId', taggedId);
        taggedQuery.first({
            success: function(someOtherData) {
                console.log(value, i, someOtherData);
            },
            error: function(taggedRecError) {
                console.log('error: ' + taggedRecError.message);
            }
        });
    });
});
Esailija
  • 138,174
  • 23
  • 272
  • 326
0

You're on the right track, this is what I think you want to do with your success parameter:

taggedQuery.first({ //.first returns the first match (.find returns all)
    success: (function(index) {
        return function(value) {
            //value is what Parse passes
            //index is your preserved index
        };
    }(i))
});
John Strickler
  • 25,151
  • 4
  • 52
  • 68
  • Thank you very much. I have just tested this (in addition to Esailija's solution), and it works. Thanks again for your time in helping. – Josh Oldham Jul 31 '12 at 10:15