Bringing setTimeout to ECMAScript

Dean Landolt dean at deanlandolt.com
Sun Mar 20 12:27:06 PDT 2011


On Sun, Mar 20, 2011 at 3:03 PM, Kyle Simpson <getify at gmail.com> wrote:

> Nowadays the clamp is there because sites use |setTimeout(f, 0)| when they
>>> really mean "run this at 10Hz" and if you run it with no delay then they
>>> swamp your event loop and possible render "wrong" (e.g. the text disappears
>>> before the user has a chance to read it).
>>>
>> I'm not convinced that this  is the meaning. I use |setTimeout(f, 0)| to
>> mean "schedule f after this event completes" or "push |f| onto the event
>> queue"; I think that is the common meaning.   A delay value of zero is
>> perfectly sensible, but we mean "zero seconds after other queued events",
>> not "zero seconds after this event".  We assume (without real evidence I
>> suppose) that UI and IO events can be queued while our JS (the caller of
>> |setTimeout(f, 0)|) runs.
>>
>
> I'd actually say that the most common meaning for `setTimeout(f,0)` is: "do
> `f` as soon as possible after the current code finishes." There's a bunch of
> places I do things like that. For instance, in IE (older versions), it's
> prudent to delay any code with a setTimeout(..., 0); that is adding script
> elements to the DOM, to avoid certain crashing race conditions. And there's
> of course dozens of other cases where similar things are a reality on the
> web.
>
> If:
>
> setTimeout(a,0);
> setTimeout(b,0);
> // some non-trivial computation
>
> ... is really to be interpreted that `a` and `b` have a non-deterministic
> ordering, that's quite counter-intuitive and in fact will definitely have
> potential to break some code across the web. On the contrary, I've never
> seen that pattern be unreliable, so I would suspect all the browsers are
> already guaranteeing that order, using some "queue" (not a "stack",
> obviously, as Jorge has been saying) for each target time.
>
> Furthermore, this pattern should also be true here, right?
>
> setTimeout(a,5);
> var then = (new Date()).getTime(), now;
> do { now = (new Date()).getTime(); } while (now < (then + 5));
> setTimeout(b,0);
>
> If in this case `b` can go before `a`, that seems like that violates the
> principle of least-surprise, because as a programmer I've basically tried to
> ensure with that snippet that both timers are set to fire at essentially the
> same time target, and if they are firing at ~ the same time, I can't see any
> expectation that makes sense except "first-come-first-served" (in other
> words, the time-target queueing).
>


This is a nice demonstration the non-determinism Brenden suggested. But you
say "firing at ~ the same time" -- that should be suspect right there --
implementations would need to deign the developer's intent. AFAICT the only
way to make this behave sanely is to take the event turn into consideration
when scheduling -- b should deterministically happen ~ 5 ms before a because
they were both scheduled in the same event turn and thus have the same
beginning time. Maybe it's not *perfect* but it's also not all that
surprising, and never ND.


>
> There are cases where non-determinism are unfortunate reality, like the
> iteration order of objects :), but I don't think that timer/event ordering
> should be one of them, if it can be avoided.


What implementation has ND iteration order of objects?

>
>
>
>  Multiple repeated calls to |setTimeout(f,0)| are bugs
>>
>
> I don't agree with that assertion at all. Two different functions might
> "queue up" two different snippets to happen "as soon as possible, later",
> each of them using their own setTimeout(..., 0).
>
>
Also, if this were really the case, node wouldn't have process.nextTick.
Again, it all comes down to fine-grained control over turns of the event
loop.


>
>  and setInterval of zero would be a bug.
>>
>
> setInterval(...,0) may be silly, but that doesn't mean it's a bug. It means
> "make this happen as fast as possible", just like above where
> setTimeout(...,0)  means "make this happen as soon as possible".
>
> The "swamping" would occur if setInterval(f,0) was actually going to spin
> in sub-millisecond speeds. It could also occur if you fake setInterval with:
>
> function f() {
>  // ...
>  setTimeout(f,0);
> }
> f();
>
> But in either of those cases, I don't see why there'd be any reason for
> "clamping" at anything higher than 1ms (being the smallest unit of time I
> can address with the API anyway)?
>

There's no theoretical reason to clamp even at 1ms -- just historic *break
the web *reasons. The non-determinism problem seems like a good
justification for TC39 to considering formalizing the event loop. Still, if
you all standardize anything it probably shouldn't be setTimeout with its
clamping baggage -- let the web platform crowd deal with that mess :)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110320/8c17ea13/attachment-0001.html>


More information about the es-discuss mailing list