Reputation: 2923
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:
Is there a way to pass variables to an anonymous callback function instead of creating a named function?
Upvotes: 0
Views: 116
Reputation: 943157
It doesn't matter if a function is named or anonymous. All that matters is that:
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}`);
});
Upvotes: 1
Reputation: 9285
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();
});
}
Upvotes: 1