0

I am trying to execute a function every hour. This essentially validates documents from a MonoDB. However, at time of first interval the application crashes throwing the following error:

timers.js:252  
 callback.apply(this, args);  
          ^  

TypeError: Cannot call method 'apply' of undefined  
    at wrapper [as _onTimeout] (timers.js:252:14)
    at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)  

Here are snippets from my files:

validator

function validate() { ... }

module.exports = {
  validate : validate
}

www

var validator = require('../lib/validator');
var app = require('../app');

app.listen(3000, function() {
  setInterval(validator.validate(), 360000);
}
wshaheer
  • 92
  • 10

3 Answers3

5

setInterval() takes a method reference. You only need to remove the parentheses from where you pass in the callback:

setInterval(validator.validate, 360000);

Essentially, the second time the interval fires it would be trying to invoke the result of your first call to validate() instead of the function itself, thus the error. Here's a similar test in client-side JavaScript (setInterval behaves the same way to my knowledge):

function setTime() {
  $('#currentDateTime').html(new Date());
}

$(function() {
  setInterval(setTime, 1000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="currentDateTime"></div>

ALSO As an interesting just in case to this answer, I found another user who appears to be passing the method reference in properly but getting a similar error. The comment supposes that maybe there could be an upper bound to the timeout being hit (size of int? signed int? just guessing).

Node.js crashes when using long interval in setinterval

Community
  • 1
  • 1
Andrew Mount
  • 391
  • 2
  • 6
  • that's interesting, because I've tried the same approach within the **app.js** file which was yielding the same result. But since moving it inside `app.listen() { ... }` it's working fine. I think it might be because I had other timers such as `setImmediate()`. However, I would still like to know whether `setInterval()` in my case would fire the event once at application start and then at every set interval – wshaheer Jul 17 '15 at 04:09
  • Unless I'm missing something, I believe the setInterval() implementations are the same between the client and Node. I would run a test where you only pass the method reference and use a very quick timer to see if it's firing as designed. I'd be interested to know if the Node implementation is indeed different but it wouldn't make much sense that the interval would use the result of your method call vs the reference when invoking at the time period. – Andrew Mount Jul 17 '15 at 04:17
2

You are not calling setInterval correctly... it should be wrapped in it's own function scope.

app.listen(3000, function() {
  setInterval(function() { validator.validate() }, 360000);
}
Jordan
  • 359
  • 3
  • 12
1

Try the following snippet.

app.listen(3000, function() {
  setInterval(validator.validate.bind(validator), 360000);
}

setInterval takes a function as the first parameter, and your code snippet calls validator.validate() immediately (and I assume that function call does not return a function).

benbotto
  • 2,291
  • 1
  • 20
  • 32