Reputation: 14041
I am writing some Javascript/jQuery code that requires me to make lots of requests to various APIs. I have come across this problem many times and this is just a basic example of one instance of it.
The code makes an asynchronous request to a server and then if a condition with the returned data is not met, the code makes another request. The second request has a callback that contains much of the same logic as its parent. I know that I am avoiding repetition by calling the returnFunction
in each callback but is there a way to avoid this altogether?
var container = [];
$.getJSON("http://www.url.com/api/?callback=?",
{ data: "mydata" },
function(data) {
if(!data.length) {
// No results
} else {
// Put the results into an array
$(data).each(function(k, v){
container.push(v.some_data);
});
// If the query did not return enough results
if(data.length < limit) {
var number_missing = limit - data.length;
// Get some more results and append to the array
myFunctionToGetSomethingElse(number_missing, function(response){
// Add these results to the array
$(response).each(function(k, v){
container.push(v.some_data);
});
// Do something with this data
returnFunction(response);
});
} else {
// Do something with the result
returnFunction(data);
}
}
});
How would you recommend I avoid the repetition of the code inside the callbacks? Is this the only possible way?
Upvotes: 1
Views: 437
Reputation: 355
// <script src="http://code.onilabs.com/0.9.1/oni-apollo.js"></script>
// <script type="text/sjs">
// install stratified versions of jquery functions; see below
require('jquery-binding').install();
// Note the extra '$' in $getJSON. This is the 'stratified' version of
// getJSON. Instead of taking a callback it blocks until the result is
// available. The browser will stay responsive during that time.
var data = $.$getJSON("http://www.url.com/api/?callback=?", {data: "mydata"});
if (!data.length) {
// no results
} else {
$(data).each(function(k, v){
container.push(v.some_data);
});
if (data.length < limit) {
var number_missing = limit - data.length;
// assuming your function 'myFunctionToGetSomethingElse' uses
// something like $.$getJSON inside, again you don't need a
// callback
$(myFunctionToGetSomethingElse(number_missing)).each(
function(k, v){
container.push(v.some_data);
});
}
}
// console.log(container);
// do something with the result. E.g. call returnFunction() or put the
// code from returnFunction here directly
You can get more information on http://onilabs.com/apollo
Upvotes: 2
Reputation: 40336
I don't have an answer to your question - how to eliminate the duplication - but one way to make this a bit cleaner would be to flatten it out with early returns.
$.getJSON("http://www.url.com/api/?callback=?",
{ data: "mydata" },
function(data) {
if (!data.length) {
// No results
return;
} // no "else" needed, because we left the function
// Put the results into an array
$(data).each(function(k, v){
container.push(v.some_data);
});
// if the query DID return enough results, return them and exit
if (data.length >= limit {
// Do something with the result
returnFunction(data);
return;
} // again, no "else" needed; we don't need to deeply nest the code
// The query did not return enough results
var number_missing = limit - data.length;
// Get some more results and append to the array
myFunctionToGetSomethingElse(number_missing, function(response){
// Add these results to the array
$(response).each(function(k, v){
container.push(v.some_data);
});
// Do something with this data
returnFunction(response);
});
}
});
I would think you could wrap the array-loading loop into its own function; I can't see why that would be a problem, but I don't know javascript well enough to say so with absolute confidence.
Upvotes: 0