0

I am using the Github API to retrieve data about one of my repos and I am running into trouble with callback functions and recursive functions overlapping (as in recursive functions with callbacks attached to them)

Here is the script on jsfiddle as well as below:

(function () {
    'use strict';

    function makeAJAXCall(hash, cb) {
        $.ajaxSetup({
            accept: 'application/vnd.github.raw',
            dataType: 'jsonp'
        });

        $.ajax({
            url: hash,
            success: function (json) {
                //console.info(json);
                // Time for callback to be executed
                if (cb) {
                    cb(json);
                }
            },
            error: function (error) {
                console.error(error);
                // an error happened, check it out.
                throw error;
            }
        });
    }

    function parseBlob(hash) {
        return makeAJAXCall(hash, function (returnedJSON) {  // no loop as only one entry
            console.log(returnedJSON.data);
            return returnedJSON.data.content;
        });
    }

    function walkTree(hash) {
        var tree = 'https://api.github.com/repos/myusername/SVG-Shapes/git/trees/' + hash;
        return makeAJAXCall(tree, function (objectedJSON) {
            var objectList = [], i, entry;
            for (i = 0;  i < objectedJSON.data.tree.length; i += 1) {
                entry = objectedJSON.data.tree[i];
                //console.debug(entry);
                if (entry.type === 'blob') {
                    if (entry.path.slice(-4) === '.svg') {     // we only want the svg images not the ignore file and README etc
                        //console.info(entry.path)
                        objectList.push(parseBlob(entry.url));
                    }
                } else if (entry.type === 'tree') {
                    objectList.push(walkTree(entry.sha));
                }
            }
            if (cb) {
                console.log(objectList);
                cb(objectList);
            }
            return objectList;
        });
    }

    $(document).ready(function () {
        var returnedObjects = walkTree('master', function (objects) {     // master to start at the top and work our way down
            console.info(objects);
        });
    });
}());

The JSON returned is either blog (file) or tree (directory). If it is a tree the walkTree function is called again. I do not understand how the callback will behave here as well as how to get the data it (should) return(s) out of the function and into the final block at the very bottom.

Can someone clarify how I should be doing this?

Doug Miller
  • 1,316
  • 4
  • 24
  • 46

1 Answers1

4

Ajax calls are usually asynchronous. That means that when you make the ajax call, it just initiates the ajax call and it finishes some time later. Meanwhile, the rest of your code after the initiation of the ajax call keeps running until completion.

Then, sometime later when the ajax call finishes, the success function is called and, in your case, the callback function gets called by the success function. It is important to understand that the success function is called much later after the makeAJAXCall() function has already finished.

Thus, you cannot return the ajax data from the makeAJAXCall() function because it isn't known yet when that function returns.

In fact, the only two places you can use the results of the ajax call are:

  1. In the success handler directly
  2. In some function that the success handler calls which in your case it the callback function.

So, it is doing you no good to return returnedJSON.data.content; from the callback function. That is just returning into some internal part of the ajax infrastructure and doing nothing. That return value will just be dropped on the floor and lost.

Instead, you need to put whatever code wants to use returnedJSON.data.content right there in that callback function (or pass it to another function with a function call).

Ajax is asynchronous. That means you can't do normal sequential programming when using ajax. Instead, you have to do event driven programming where the event in this case is the callback that is called upon a success completion of the ajax call. All work that uses those ajax results needs to commence from that success handler or the callback that is called from it.

jfriend00
  • 683,504
  • 96
  • 985
  • 979