TWLATL
TWLATL

Reputation: 2879

Continuously polling $.ajax request issue

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:

http://jsbin.com/doneka/3/

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

Answers (2)

Howard Renollet
Howard Renollet

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

Palpatim
Palpatim

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

Related Questions