Has this seen adoption? #3
Comments
It's adopted in Node, but I'm not aware of it being used in any non-Trident/EdgeHTML browsers. |
Node, IE and Edge are the only implementations. I believe it is fair to say that the spec needs work. At the same time, there is massive adoption of setImmediate in the real world. I just checked and we see ~30% of navigations making use of it including Facebook, YouTube, Yahoo, Ebay, Roblox, many other Google properties and many Microsoft sites. |
I came across https://w3c.github.io/setImmediate/ today and was wondering the same thing. Is there still hope that this will be implemented everywhere? If so, should there be web-platform-tests? If not, can the status of the spec be updated to something like https://w3c.github.io/geofencing-api/? |
25% of navigations in Microsoft Edge execute setImmediate including the following sites in the top 20: Facebook, YouTube, Google, Gmail, Bing, MSN, Ebay, GitHub. The setImmediate spec has not been updated, because conversations about the hole it fills in prioritization/input blocking between microtasks and setTimeout(0) have generally been nonstarters. Tests have not been added for the same reason. I'm happy to revive the discussions and potentially update the spec at any point. |
So, in other words, this isn't on a path for removal in Edge, but expected to stay around and hopefully be picked up by others some time down the line? |
At FB we would love to see this api formalized. It's pretty common to have abstractions that want to do something "soon" for some definition of soon. For example waiting until the current slice of execution has finished to batch up multiple requests into a single request. I think we'd need to figure out exactly what rules we want to have around it, but I imagine we could come up with something useful |
I have the same question as @annevk in #3 (comment) |
IMO exposing something closer to "post a task" that does not require allocating a MessageChannel would be useful. Its a primitive that sites use. Trying to force them into Promise or rAF seems a bit paternalistic to me. At least based on recent discussions in the gecko bug we are in a better place to be able to implement it with some mitigations for abuse. We would need spec language to allow us to implement those mitigations. Marking setImmediate() a separate task source may be enough for that to work. (Ordering not guaranteed with anything else, etc.) |
My issue is that setImmediate is the least useful primitive among queueMicrotask, requestAnimationFrame, and requestIdleCallback. I have seen no legitimate use cases that aren't better covered by those three. (One "non-legitimate" use case is working around bugs in requestAnimationFrame, which apparently fires after render in two browsers.) So I'd much rather prioritize implementing queueMicrotask and fixing requestAnimationFrame bugs, and performing appropriate outreach to get developers to switch to the more appropriate choice (e.g. by updating popular promise polyfills, or those top domains). Once we've done that we can reevaluate whether this primitive should be web-exposed, or whether it's too much of a footgun. |
queueMicrotask blocks input and the render steps till all of enqueued microtasks are complete. We are starting to see developers make mistakes by overqueueing these without understanding the impact. @jackarchibald will be going over this in an upcoming talk he is giving in an attempt to educate developers. requestAnimationFrame is delayed until the render steps. This means that sites are giving up ~1-15ms of time if requestAnimationFrame is used to schedule a callback. requestIdleCallback is designed for non-critical work and schedules the callback in the next frame. This is a GREAT API but has a different purpose than setImmediate. setImmediate fills the hole between queueMicrotask and requestAnimationFrame by creating a "high priority" task source allowing a callback to be scheduled immediately while allowing a UA to prioritize an input task such as a link click to be processed. setImmediate is very close to semantically equivalent to setTimeout(0) but prior research has found that setTimeout/setInterval(0/1) are widely and badly used and that all UAs have added heuristics to mitigate their usage. setImmediate does not seem to have fallen victim to the same issues as libraries seem to have been more thoughtful in adopting it. We have some time on our schedule for the Web Performance Working Group on Tuesday for TPAC 2017 to review this issue. I'll add the specific scheduling slot to this issue after @igrigorik and I lock the time slot later today. |
From our implementation standpoint queueMicrotask is more problematic because its easier to abuse and there is no mitigation strategy. Its a stealth sync loop and the only option is to throw up UX asking the user to stop the page. Tasks like setImmediate() can be prioritized, yielded, etc among other work in extreme cases to avoid problems. You also in spite of your assertions about no used cases I see web developers saying they have use cases: https://twitter.com/youyuxi/status/915949863644418050 |
Todd, I'd be interested in talking about setImmediate() next week, but I probably can't make this since SW meeting is also on Tuesday. |
Yes, queueMicrotask is indeed a sync loop; that's not an issue. I mean that it should be used in the promise libraries which are probably accounting for a large percentage of setImmediate usage. I agree web developers say that they have use cases. In all cases (including the linked tweet) when we've drilled down we've found out they are confused about what tasks and microtasks mean, and when animation frame timing is. High-priority tasks which you want to allow the UA to still do work before it happens should be done via requestIdleCallback with a timeout option indicating how soon you require execution. |
I'll just say I disagree with your conclusions here. I don't think Evan or Kyle are confused about the difference between tasks and microtasks.
This is dramatically different than posting a task to the event queue. The abuse mitigations I mentioned would be quite different than requestIdleCallback. My intent would be to design them so that well behaved sites don't encounter them at all. If the code is fine with potentially long delays then, sure, rIC is better. But its not a replacement for setImmediate(). Anyway, I don't see how exposing setImmediate(), which is already in a browser, would prevent developers from using promises, rAF, or rIC if they prefer those behaviors. |
rIC does not have potentially long delays if used with a timeout option. |
So you are saying you think rIC with a timeout should escape the nested clamping we do for Looking at our code I believe we enforce clamping on rIC timeouts. |
I assumed everything non-sync (so rIC and setImmediate both) would be subject to the clamping. If not now, they would be after a year when the abuse starts. |
My exact point is we are in a position to implement setImmediate() without clamping, but also avoid abuse via prioritization/yielding under extreme conditions. |
I don't see why you wouldn't do the same for rIC then. |
We could in theory, but it would mean implementing a separate timer subsystem from setTimeout(). I don't really want to do that. Also, its unclear that would be something devs could rely on cross-browser. I personally also have problems with rIC as a replacement for setImmediate() on conceptual grounds. Maybe this is just me, but I think about these primitives on a continuum:
If someone is calling Anyway, that's just me. |
What do you think the intention of setImmediate is?
"post a task" is not a good example of this. It's intended for getting from the background thread ("in parallel") back to the main thread (event loop). It isn't a primitive meant for use from the main thread. Similarly, there's a degenerate case where you postMessage to yourself to go from the main thread ... back to the main thread. That's not what postMessage is generally for; it's for going from one thread (or at least realm) to a different thread (realm). So I don't think this point on the continuum is meaningful. If you want fast, you should want sync, and use microtasks.
Similarly, you shouldn't be using setTimeout as a "fast/medium" way of scheduling work. You should be using it for time-based scheduling. When I was a web developer, every instance of setTimeout(f, 0) was just working around our own poor coding (or sometimes a browser bug), or it was a poor-person's queueMicrotask. In general I don't think you can meaningfully express "I want to do this work fast/medium/slow". My breakdown would be:
I don't think there's a use case for setImmediate in here. So far the use cases that have been expressed have been along the lines of "I want this to happen soon but not block user input". That's exactly what requestIdleCallback is for. |
I'm asking since we still have https://bugzilla.mozilla.org/show_bug.cgi?id=686201 open, but the specification hasn't been maintained since 2011 and I'm not aware of other implementations.
The text was updated successfully, but these errors were encountered: