简体   繁体   中英

Pass data back to anonymous function via callback?

I've been researching callback functions in the JavaScript language lately and during my testing I've encountered an issue that I didn't foresee, but once I encountered it, I understood what the issue was most likely to be.

I've written two methods that work together to call the Stack Exchange API for learning purposes. The first builds the request URL and the second calls the web service itself.

function getSEWebServiceResponse(request, callback) {
    var apiRoot = 'https://api.stackexchange.com/2.2/';
    var key = 'key=s29XM)Eqn2x3YxhjLgFwBQ((';
    if (request.indexOf('?') >= 0)
        key = '&' + key;
    else
        key = '?' + key;

    getWebServiceResponse(apiRoot + request + key, callback);
}
function getWebServiceResponse(requestUrl, callback) {
    var request = new XMLHttpRequest();
    request.open('GET', requestUrl, true);
    request.onload = function() {
        if (request.status < 200 || request.status >= 400)
            callback("An unexpected error occurred.");
        else
            callback(JSON.parse(this.response));
    };
    request.send();
}

Now, this implementation is straightforward, but the issue I ran into was that passing back the response resulted in undefined and I believe the cause is that I'm using an anonymous function as the callback for getSEWebServiceResponse :

function getAssociatedAccounts(accountID, callback) {
    var url = 'users/' + accountID + '/associated';
    getSEWebServiceResponse(url, function() {
        if (!this.items) // this.items is undefined.
            return;

        var accounts = sortAccountsByReputation(this.items);
        //... DO MORE STUFF
        callback();
    });
}

I believe the simple solution is to create a defined function instead (but I feel that there should be a way to do it with anonymous functions):

function getAssociatedAccounts(accountID, callback) {
    var url = 'users/' + accountID + '/associated';
    getSEWebServiceResponse(url, processAssociatedAccounts);
}
function processAssociatedAccounts(response) {
    if (response.items)
        return;

    var accounts = sortAccountsByReputation(this.items);
    //... DO MORE STUFF
    callback();
}

A few related posts that didn't offer solutions:

  • This one is the reverse of what I want to do.
  • This one doesn't pass arguments.

Is there a way to pass variables to an anonymous callback function instead of creating a named function?

In your original getAssociatedAccounts with an anonymous callback, you do not accept the response a parameter. Changing it to the following should work

function getAssociatedAccounts(accountID, callback) {
    var url = 'users/' + accountID + '/associated';
    getSEWebServiceResponse(url, function(response) { // accepted response as parameter
        if (!response.items) // this.items is now response.items.
            return;

        var accounts = sortAccountsByReputation(response.items);
        //... DO MORE STUFF
        callback();
    });
}

It doesn't matter if a function is named or anonymous. All that matters is that:

  • You pass arguments when you call it
  • It does something with those arguments

For example:

 let counter = 1; function i_take_a_callback(callback) { callback(counter++); } function i_have_a_name(value) { console.log(`I have a name and am logging ${value}`); } i_take_a_callback(i_have_a_name); i_take_a_callback(function(value) { console.log(`I am anonymous and am logging ${value}`); }); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM