w3c / requestidlecallback

Cooperative Scheduling of Background Tasks
https://w3c.github.io/requestidlecallback/
Other
50 stars 19 forks source link

Should pending idle callbacks in the queue be run when the page is unloaded/backgrounded? #73

Closed philipwalton closed 5 years ago

philipwalton commented 6 years ago

Analytics and measurement code is a great use case for requestIdleCallback(), but there are a small set of situations in which you wouldn't want to use requestIdleCallback() for fear that the callback would never run. Some example of this are:

Because some analytics tracking functions need to be run urgently, most analytics libraries just run all their analytics code synchronously because they don't know how the page author is going to use their library.

If requestIdleCallback() could provide some sort of guarantee that a callback will be run before a page is unloaded, put into bfcache, or the user switches tabs/apps, then I think all analytics vendors would switch to using it when available, in all situations.

That seems like a big win to me. Thoughts?

tdresser commented 6 years ago

@spanicker

rmcilroy commented 6 years ago

There was some discussion on this idea in https://github.com/w3c/requestidlecallback/issues/3. The consensus was that it is possible to achieve this by having logic in an onunload / onbeforeunload handler to check whether the task has been run, and if not perform the operation. Given that setTimeout and similar callback mechanisms don't have an option to guarantee they will be executed either, we decided to be consistent with them and avoid adding complexity to the API.

spanicker commented 6 years ago

@philipwalton - could you elaborate on why lifecycle events (pagevisibility, freeze and even unload) don't suffice? The analytics library would have code for steadystate and also hooking into these handlers.

philipwalton commented 6 years ago

@spanicker lifecycle events do suffice (and it's what I ended up doing for my case), it's just non-trivial to wire it all up yourself. It's also really easy to get wrong since there are a lot of browser inconsistencies in this space (e.g. the hoops I had to jump through here in the PageLifecycle.js).

Furthermore, it's not the case that a developer can just simply run the queued callbacks in a visibilitychange/freeze/unload handler because that will mean the callbacks may be executed out of order (e.g. if any of the requestIdleCallback() callbacks enqueue more callbacks), so the only want to handle this in an unload situation is to use microtasks, which may require additional polyfills depending on the browser support needed.

It's definitely possible to do it yourself, it's not not super easy to do right. I imagine most analytics libraries would rather just run the code sync to ensure it happens rather than deal with the challenges of doing it right (and that's unfortunate).

I may do a blog post or something advocating the right way to do this.

philipwalton commented 5 years ago

I wrote up my experience handling this issue in a blog post: https://philipwalton.com/articles/idle-until-urgent/

I think we can close this for now, since realistically developers would still need to handle this themselves until all rIC implementations were the same. Also, @spanicker has a proposal for a high-level scheduling API, and that's probably a better place to address this type of concern anyway.