试图通过填写对象来理解函数和回调范围

时间:2012-03-15 11:18:22

标签: javascript

我已经使用Github API创建了一些函数来检索数据。我有回调来获取数据,但我确定如何理解函数退出的位置以及何时停止修改。

例如,在下面的代码中,在第一个函数中,当AJAX调用成功时,回调在第二个函数中执行,其中数据被操纵。这是否意味着不需要或使用第一个函数中的返回值?而在第二个函数中使用的数据是推送到数组然后返回数组,或者是返回(空)数组的另一种方式,然后回调就完成了它。

我最终试图将回调中的数据转换为对象,并从父函数返回该填充的对象。

function makeAJAXCall(hash, cb) {
    var returnedJSON, cb = cb, hash = hash;
    $.ajax({
        accepts: 'application/vnd.github-blob.raw',
        dataType: 'jsonp',
        url: hash,
        success: function (json) {
            console.info(json);
            returnedJSON = 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;
        }
    });
    return returnedJSON;
}

function parseBlob(hash) {
    var objectedJSON, objectList = [], i;
    objectedJSON = makeAJAXCall(hash, function (objectedJSON) {  // no loop as only one entry
        objectList.push(objectedJSON.content);
    });
    return objectList;
}

function walkTree(hash) {
    var objectedJSON, objectList = [], i, entry;
    var hash = 'https://api.github.com/repos/myAccountName/repo/git/trees/' + hash;
    objectedJSON = makeAJAXCall(hash, function (objectedJSON) {
        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));
            }
        }

    });
    console.info(objectList);
    return objectList;
}

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

2 个答案:

答案 0 :(得分:2)

这里你正在进行AJAX调用A是指异步,即你的成功/错误回调将异步执行。

makeAJAXCall将在执行$ ajax的成功/错误之前返回。

因此objectedJSON = makeAJAXCall会返回undefined

function makeAJAXCall(hash, cb) {
    $.ajax({
        accepts: 'application/vnd.github-blob.raw',
        dataType: 'jsonp',
        url: hash,
        success: function (json) {
            // this function will be executed after getting response from server 
            //ie Asynchronously
            //here cb passed from the makeAjaxCall exist in the closure scope
            if (cb) {
                cb(json);
            }
        },
        error: function (error) {
            console.error(error);
            // an error happened, check it out.
            throw error;
        }
    });
}

现在,当您调用makeAjaxCall时,您传递的回调函数将存在于$ .ajax的闭包范围内,并将在服务器响应成功时执行

makeAJAXCall(hash, function (objectedJSON) {  
    //objectJSON contains the response from server
    // do all your operations using server response over here or assign it to a global variable
});

检查以下链接

https://developer.mozilla.org/en/JavaScript/Guide/Closures

https://mikewest.org/2009/05/asynchronous-execution-javascript-and-you

或者您可以使用async:false同步进行ajax调用,这是非常不推荐的

function makeAJAXCall(hash, cb) {
    var returnedJSON;
    $.ajax({
        accepts: 'application/vnd.github-blob.raw',
        dataType: 'json',
        async : false, //this will make it in sync
        url: hash,
        success: function (json) {
            console.info(json);
            returnedJSON = json;
        //now makeAJAXCall will wait for success to complete and it will return only after executing success/error 
        // Time for callback to be executed
            if (cb) {
                cb(json);
            }
        },
        error: function (error) {
            console.error(error);
            // an error happened, check it out.
            throw error;
        }
    });
    //will wait for success/error before returning
    return returnedJSON;   
}

在上述情况下,您的代码将起作用

答案 1 :(得分:1)

function makeAJAXCall(hash, cb) {
    var returnedJSON, cb = cb, hash = hash;
    return $.ajax({
        accepts: 'application/vnd.github-blob.raw',
        dataType: 'jsonp',
        url: hash,
        success: function (json) {
            console.info(json);
            returnedJSON = 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) {
    var objectedJSON, objectList = [], i;
    objectedJSON = makeAJAXCall(hash, function (objectedJSON) {  // no loop as only one entry
        objectList.push(objectedJSON.content);
    });
    return objectList;
}

function walkTree(hash) {
    var objectedJSON, objectList = [], i, entry;
    var hash = 'https://api.github.com/repos/myAccountName/repo/git/trees/' + hash;
    objectedJSON = $.when(maxAJAXCall)
                    .then(function(){
                          //Write the callback  
                     }); 

使用$ .when()。then()来调用ajax并更好地管理回调。 .When