RE: Queuing promise operations via microtasks rather than tasks

Yeah, I think all involved agree that microtasks is how it should be handled. But there's so much confusion about how to spec the event loop and the different task queues, nobody has actually gotten around to updating the spec in that regard. We should probably add a note saying "this will probably use microtasks" for now.

The best summary of the desired situation that I've seen has come from Yehuda, at https://www.w3.org/Bugs/Public/show_bug.cgi?id=22296#c16


________________________________
From: Igor Minar [iminar@google.com]
Sent: Thursday, July 18, 2013 02:52
To: www-dom@w3.org
Subject: Queuing promise operations via microtasks rather than tasks

The dom promises spec specifies that operations like fulfillment or rejection should be handled by queueing a task<http://dom.spec.whatwg.org/#promises-model> to perform this operation.

Using the task queue however means that if several promises are queued to be fulfilled at the same time, the browser will be forced to re-render the dom after each promise fulfillment (supposing that each of the resolution will result in dom operation that needs to be reflected in the UI).. See point 4.3 in the event loop processing model<http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#processing-model-4>.

This kind of processing model will result in unnecessary flicker, which will impact the user experience.

I think that all of the flicker could be avoided and the performance of the apps could be improved if the microtasks similar to those used by the mutation observers<http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#perform-a-microtask-checkpoint> were used instead of tasks.

Is this something that could be considered?




A concrete example:

given a function fetchJSON similar to the one used in promise intro and a a simplistic function updateDOM:

function updateDOM(location) {
  return function(data) {
    document.getElementById(location).textContent = data
  };
}

['widget1', 'widget2', 'widget3'].forEach(function(widgetName) {
  fetchJSON('/data/' + widgetName).then(updateDOM(widgetName));
});

Everything would work as expected... until, we modified the fetchJSON function to fulfill its promise from an in-memory cache that has been primed already for all 3 of our widgets. So unlike before all three fetchJSON promises are now being scheduled to be fulfilled from a single task, but the fulfillment will result in three new tasks each of them performing the dom update and causing new re-rendering.

It would be way more efficient and the user experience would be improved significantly if the fulfillment happened in a single new tasks (preserving the async resolution) and only once all of the dom manipulation is done, the browser would render the UI at the final state just once, skipping all the intermediate updates.

Received on Thursday, 18 July 2013 14:13:50 UTC