Skip to content

Instantly share code, notes, and snippets.

@thecountofzero
Last active December 16, 2015 03:49
Show Gist options
  • Save thecountofzero/5372847 to your computer and use it in GitHub Desktop.
Save thecountofzero/5372847 to your computer and use it in GitHub Desktop.
Testing for a memory leak when polling, where the polling action is issuing a findAll request
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Memory Leak Test</title>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<div id="dummy">
Click "Setup Live Binding" to initialize live binding<br/><br/>
<button class="setup">Setup Live Binding</button>
<button class="addHomer">Add Homer</button>
<button class="fetch">Fetch From Server</button>
<button class="poll">Start Polling</button>
<button class="stop">Stop Polling</button><br/><br/>
<div></div>
</div>
<script id="dummyEJS" type="text/ejs">
<% stats.each(function(s) { %>
Name: <%= s.attr('name') %>: <%= s.attr('homeruns') %> (<%= s.getAverage() %>)<br/>
<% }) %>
</script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
<script src="http://canjs.com/release/latest/can.jquery.js"></script>
<script src="http://canjs.com/release/latest/can.construct.proxy.js"></script>
<script src="http://canjs.com/release/latest/can.fixture.js"></script>
<script type='text/javascript'>
$(document).ready(function() {
var STATS = [{
"name": "Ryan Braun",
"homeruns": 2,
"atbats": 20,
"hits": 12
}, {
"name": "Troy Tulowitzki",
"homeruns": 4,
"atbats": 20,
"hits": 8
}];
can.fixture('GET /stats', function () {
return STATS;
});
Stat = can.Model({
id: "name",
findAll: "GET /stats"
}, {
getAverage: function() {
return (this.attr('hits') / this.attr('atbats')).toFixed(3);
}
});
Dummy = can.Control({
init: function (element, options) {
var self = this;
// Just some property on the control
this.counter = 0;
can.when(Stat.findAll()).then(function(stats) {
// Save a copy of the stats objects
self.stats = stats;
});
},
// Sets up live binding
'.setup click': function (el, ev) {
this.element.find('div').append(can.view('dummyEJS', {
stats: this.stats
}));
},
// Add a home run to each players stats
'.addHomer click': function (el, ev) {
this.stats.each(function(s) {
s.attr('homeruns', s.attr('homeruns') + 1);
});
},
// Fetch stats data from the server (fixture)
'.fetch click': function (el, ev) {
can.when(Stat.findAll()).then(function (stats) {
self.stats = stats;
});
},
// Start polling
'.poll click': function (el, ev) {
this.poller();
},
// Stop polling
'.stop click': function (el, ev) {
clearTimeout(this.timeoutId);
},
// This polling function just updates the stats data without making a call to the server
poll: function () {
this.stats.each(function(s) {
s.attr('homeruns', s.attr('homeruns') + 1);
s.attr('atbats', s.attr('atbats') + 3);
s.attr('hits', s.attr('hits') + 1);
});
this.timeoutId = setTimeout(this.proxy('poll'), 3000);
},
// This polling function
poller: function () {
// Increment the counter
this.counter = this.counter + 1;
// Fetch stats from server
can.when(Stat.findAll()).then(function(stats) {
// Update the control's copy of the stats objects
self.stats = stats;
// Grab the stats model for Ryan Braun
var p = Stat.model({name: 'Ryan Braun'});
// Update his number of home runs to a random number
p.attr('homeruns', Math.floor(Math.random() * 60 + 1));
});
// Store the timer ID so we can cancel the polling
this.timeoutId = setTimeout(this.proxy('poller'), 5000);
}
});
new Dummy('#dummy');
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment