Proposal: Switch position of delay and callback in signature of `setTimeout()`

# Adrian Sieber (9 years ago)

Everytime I use setTimeout(), I wonder why the the arguments are in the wrong order. Usually the callback functions comes last, but in setTimeout it's exactly the other way round.

So I propose that the order should be reversed to be consistent with other functions. Instead of setTimeout(callback, delay[, arg][, ...]) it should be setTimeout(delay, callback[, arg][, ...])

By checking the type of the first two arguments (which one is the function) backwards compatibility can be achieved.

So a polyfill would be something like:

newSetTimeout = (delay, callback, ...args) => {
  if (typeof delay === 'function') {
    setTimeout(delay, callback, ...args)
  }
  else {
    setTimeout(callback, delay, ...args)
  }
}

What do you think?

# Oriol Bugzilla (9 years ago)

setTimeout is not part of ECMAScript. You should suggest this to WHATWG instead.

Edit: But I agree with Tab Atkins this seems a very bad idea.

# Tab Atkins Jr. (9 years ago)

On Mon, Apr 25, 2016 at 10:43 AM, Oriol Bugzilla <oriol-bugzilla at hotmail.com> wrote:

setTimeout is not part of ECMAScript. You should suggest this to WHATWG instead.

And I can short-circuit the request: we can't change it. setTimeout is an old and heavily-used API, so any change like this is very likely to be backwards-incompatible.

# Boris Zbarsky (9 years ago)

On 4/25/16 1:35 PM, Adrian Sieber wrote:

Everytime I use setTimeout(), I wonder why the the arguments are in the wrong order. Usually the callback functions comes last, but in 'setTimeout' it's exactly the other way round.

First, this is the wrong list: setTimeout is defined by html.spec.whatwg.org/multipage/webappapis.html#dom-settimeout not the ES language spec.

Second, note that the delay argument to setTimeout is optional.

So a polyfill would be something like:

newSetTimeout = (delay, callback, ...args) => {
   if (typeof delay === 'function') {
     setTimeout(delay, callback, ...args)
   }
   else {
     setTimeout(callback, delay, ...args)
   }
}

Third, this is not compatible, obviously. Consider what it would do with:

setTimeout("doSomething()", 1000);

You could check for function or string, but even that is not compatible in cases like this:

setTimeout({ toString: () => "doSomething()" }, 1000);

and then you're left discussing whether such cases exist in practice and whatnot, yes?

# Adrian Sieber (9 years ago)

@Boris Well, I wasn't aware the setTimeout() has such an absolutely broken API. So I guess a clean reset would be better/easier.

How about making setTimeout() a part of ECMAscript. Maybe as Date.setTimeout() like it was done with Number.parseInt() … and this time with a saner API =D

# Isiah Meadows (9 years ago)

If it makes it into the language, I'd rather see Function.delay(timeout, callback) or, even better, Promise.delay(timeout).then(callback). The latter would also fit better with modern ES standard language APIs, IMHO. The latter has already been suggested here before, plenty of times, but AFAICT, it's relatively low priority.

Beyond that, I agree that changing setTimeout is out of scope here.