wilsonpage / fastdom

Eliminates layout thrashing by batching DOM measurement and mutation tasks
6.83k stars 240 forks source link

API proposition: fastdom.stagger() #27

Closed wilsonpage closed 10 years ago

wilsonpage commented 10 years ago

tl;dr Staggers work over several frames to prevent frame overload.

Sometimes in app we have too much DOM work to do in a single frame. If all this work is done in a single frame we will blow our frame budget and we get 'jank'. The .stagger() API could pose a solution to this:

// Run in frame 1
fastdom.stagger(function(){});

// Run in frame 2
fastdom.stagger(function(){});

// Run in frame 3
fastdom.stagger(function(){

  // Run in frame 4
  fastdom.stagger(function(){});
});
paulirish commented 10 years ago

I feel like I want that behavior by default. Like... ideally i dont have to chose write vs stagger. I dont know if my work will take >10ms.

wilsonpage commented 10 years ago

@paulirish I see what you mean. I have considered this, but I didn't really want to get into this territory. I thought it would be scary having jobs executed in different 'frames' on different devices, dependent on their performance. I felt it could lead to device specific bugs appearing in apps.

I really want to discuss this though!

The use case that I'm struggling with is working with a 3rd party scrolling library that does reads and writes whenever it wants. I can't batch this stuff!

I have three scrollable lists within one view, setting them up in a single frame is causing 3 layouts/reflows and blowing my frame budget. I want to spread this work over several frames, but I don't want conflict with any other scheduled work the rest of the app mat be doing.

wilsonpage commented 10 years ago

This functionality has been implemented in v0.8, but without expanding the API. Mainly because we needed it in the FT web app :p

The exact functionality of .stagger() can be achieved by calling the .defer() API without the first frames argument.

fastdom.defer(makeScroller); // frame 1
fastdom.defer(makeScroller); // frame 2
fastdom.defer(makeScroller); // frame 3