7

My code was working until i updated node.js to version 8.11.3

Now i always get error "callback argument must be a function" when trying to call a function with setTimeout.

function testFunction(itemid, price) {

  var url = 'https://example.com';
  var options = {
  method: 'get',
  url: url
  }

  request(options, function (err, res, body) {
    var response = JSON.parse(body);

     if(response.status == 'fail'){
        setTimeout(testFunction(itemid, price), 100);
     }
  })

}
MHB2011
  • 453
  • 1
  • 7
  • 22
  • 3
    The code never worked as intended, FYI. – Estus Flask Aug 04 '18 at 12:10
  • 4
    Agreed, @MHH, you probably just didn't notice that `testFunction` was not called after 100 ms, but rather immediately – you weren't passing the function `testFunction` as argument to `setTimeout`, but rather the result from calling it. Upgrading to Node 8.11.3 exposed your mistake, because it doesn't allow you to pass anything but a function anymore – Patrick Hund Aug 04 '18 at 12:19
  • Related: [How can I pass a parameter to a setTimeout() callback?](/q/1190642/4642212), [Calling functions with setTimeout()](/q/3800512/4642212), [Why is the method executed immediately when I use setTimeout?](/q/7137401/4642212). – Sebastian Simon Sep 30 '21 at 03:16

4 Answers4

16

Callback argument for setTimeout must be a function. Write it like this. Not tested but it should work.

function testFunction(itemid, price) {

    var url = 'https://example.com';
    var options = {
        method: 'get',
        url: url
    }

    request(options, function (err, res, body) {
        var response = JSON.parse(body);
        if(response.status == 'fail'){
            setTimeout(function () {
                testFunction(itemid, price);
            }, 100);
        }
    })
}
Keyur Ramoliya
  • 1,900
  • 2
  • 16
  • 17
9

@keyur is correct. According to the node.js timers documentation the setTimeout function takes the name of the function to execute as the first argument, the delay in milliseconds as the second argument, followed by any arguments being passed to the function.

For Example:

setTimeout(testFunction, 100, itemid, price);
Nate
  • 107
  • 1
  • 6
4

Yes, setTimeout() expects first argument as callback function. we can make use of es6 fat arrow function here you can try this!

setTimeout(() => testFunction(itemid, price), 100);

Hope this helps!

Sk96
  • 113
  • 1
  • 7
0

Q: I am getting the error "callback argument must be a function" when trying to call a function with setTimeout. Why?

A: setTimeout(testFunction(itemid, price), 100); You have accidentally pushed the output of testFunction as the first argument of setTimeout which it is suppose to be a function and hence the error.

What you could do is, pass in a function and call the testFunction recursively from there.

Example:

function test(itemid, price) {
    console.log("hello => " + itemid + ", " + price);
    if (price < 50) {
      setTimeout(() => { test(itemid, price + 10) }, 100);    
    }
}

test(100, 10)
Samuel Toh
  • 18,006
  • 3
  • 24
  • 39