Reputation: 2879
I'm having an issue with a continuously polling $.ajax request. The issue I'm running in to is how to have it execute immediately first, and then execute on the interval set in the setTimeout call.
Code example:
myObj = {};
var output = '';
var items = '';
myObj.displayItems = function() {
console.log('displayItems ran');
output = '';
$.each(items, function(index, val) {
output += '<li>' + val.player.firstName + ' ' + val.player.lastName + '</li>';
});
$('#content').html(output);
};
$(document).ready(function() {
(function loadData() {
setTimeout(function() {
console.log('loadData ran....');
return $.ajax({
url: '//jsbin.com/xinixa/1.json',
type: 'GET',
dataType: 'json',
cache: false,
success: function(data) {
items = data.apiResults[0].league.season.draft.rounds[0].picks;
loadData();
myObj.displayItems();
},
});
}, 3000);
})();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div id="content"></div>
</body>
</html>
Whenever I refactor to have the setTimeout call inside the function, I get errors. If I make the function not self executing, I get errors as well.
Upvotes: 0
Views: 162
Reputation: 4739
If I understand you correctly, then this should work for you. See it here
myObj = {};
var output = '';
var items = '';
myObj.displayItems = function () {
console.log('displayItems ran');
output = '';
$.each(items, function (index, val) {
output += '<li>' + val.player.firstName + ' ' + val.player.lastName + '</li>';
});
$('#content').html(output);
};
$(document).ready(function () {
(function loadData() {
console.log('loadData ran....');
$.ajax({
url: '//jsbin.com/xinixa/1.json',
type: 'GET',
dataType: 'json',
cache: false,
success: function (data) {
items = data.apiResults[0].league.season.draft.rounds[0].picks;
myObj.displayItems();
setTimeout(loadData, 10000);
},
});
})();
});
The only part I changed was in your loadData function. The method is still immediately invoking, but I moved the window.setTimeout()
into the success callback (I changed the timeout to 10s for testing). This sets the timeout after the previous successful callback which effectively sets up polling.
If you watch the console, you can see that loadData()
executes immediately, and each subsequent call executes 10 seconds after the previous call.
Hope this helps. Let me know if there's anything else I can help you with.
Upvotes: 1
Reputation: 9262
I'm not sure whether you're using "refactor" here the way I understand it, but restructuring your code is going to help a lot in diagnosing the problem. Deeply nested functions like you've got are rarely necessary, and nearly always confusing. Here's a quick & dirty refactor to remove nesting. I'm not sure if it actually accomplishes your goal, but it does execute, without errors, continuously. DEMO:
var myObj = {};
var output = '';
var items = '';
myObj.displayItems = function() {
console.log('displayItems ran');
output = '';
$.each(items, function(index, val) {
output += '<li>' + val.player.firstName + ' ' + val.player.lastName + '</li>';
});
$('#content').html(output);
};
var loadData = function() {
setTimeout(makeAjaxRequest, 3000);
};
var makeAjaxRequest = function() {
console.log('makeAjaxRequest running');
return $.ajax({
url: '//jsbin.com/xinixa/1.json',
type: 'GET',
dataType: 'json',
cache: false,
success: successHandler,
});
};
var successHandler = function(data) {
items = data.apiResults[0].league.season.draft.rounds[0].picks;
loadData();
myObj.displayItems();
};
$(document).ready(loadData);
A couple more areas for improvement:
Remove the globally-saved state in output
and items
. output
could easily be refactored into state on the myObj
object, and items
should be a parameter to your displayItems()
function.
While you're at it, rename myObj
:)
I'm not sure whether setTimeout
is the correct function to use here; if you really want something that repeats every 3 seconds, why not use setInterval
instead?
Upvotes: 1