Bug Tracker

Opened 6 years ago

Closed 6 years ago

Last modified 6 years ago

#9867 closed enhancement (wontfix)

built-in improvements to responsive-ness of Deferred Promises

Reported by: jokeyrhyme Owned by: jokeyrhyme
Priority: undecided Milestone: None
Component: deferred Version: 1.6.2
Keywords: Cc:
Blocked by: Blocking:


It's a well-known technique in JavaScript to break computationally intensive tasks into asynchronous blocks using setTimeout(fn, 0). My understanding is that it prevents the UI thread from being starved of execution time, so the UI is still responsive.

My suggestion is for Deferred.resolveWith (and therefore, Deferred.resolve) to implement this setTimeout(fn, 0) technique somehow. That way we can use Deferreds to manage our asynchronous blocks, and automatically benefit from a silky-smooth user experience. This does mean additional anonymous functions would be created, and I suppose there could be issues with animation timings.

Change History (7)

comment:1 Changed 6 years ago by ajpiano

Owner: set to jokeyrhyme
Status: newpending

Thanks for your time and interest in helping out the jQuery project! Unfortunately, this proposal is unsuitably vague. While it is certainly within the realm of possibility to somehow leverage Deferreds when doing the setTimeout(fn, 0) technique you describe above, the idea that we can "somehow implement it" into Deferreds and that will autmagically translate into a more responsive UI is not something we can use as a basis for a feature.

Is there a real world use case or implementation of this that you can point to, or can you describe in more detail what you imagine the repercussions on the jQuery API would look like?

For what it's worth, I can't see how adding a timeout into Deffered.resolveWith is a particularly wise idea.

Version 0, edited 6 years ago by ajpiano (next)

comment:2 Changed 6 years ago by jokeyrhyme

Status: pendingnew

Sorry about the vagueness.

The application I am working on performs various computationally-intensive tasks, at it also performs fairly intensive DOM manipulations (large insertions, etc). Some of these tasks are asynchronous (like AJAX, or HTML5 File API, Web Workers) and some of these are synchronous (performing XSLT, element searches, math, etc).

I am currently using Deferreds to break these tasks into smaller chunks. I then use the when-then mechanism to force serial execution upon otherwise potentially-parallel tasks (only where sequence must be preserved).

Something I have noticed is that if I don't throw setTimeout(fn, 0)'s in myself, then the UI for the application will lock-up at times. Looking at the source code for jQuery Deferred Promises, it seems resolves/rejects lead directly into then/fail/done/always, with no room given for the UI to catch up in-between.

To me, it seems that Deferreds really seem to be all about keeping JavaScript responsive (besides providing greater control over asynchronous tasks). My suggestion / question is whether it would be feasible to transparently insert the setTimeout(fn, 0) technique into the current sequence of resolve->then, so that UIs are automatically more responsive.

I am targeting mobile WebKit and mobile Gecko so far. In testing, I have noticed that without the setTimeout technique, my application locks up the UI for 30-60 seconds at times. I guess I am trying to be lazy and avoid having to manually insert setTimeouts into my own code, but to have it done transparently by jQuery Deferreds.

I would not expect the jQuery API to visibly change for developers. However, some control over the timeout interval itself (defaulting to 0) might be appropriate via a jQuery constant, similar to the jQuery.fx.interval constant.

Last edited 6 years ago by jokeyrhyme (previous) (diff)

comment:3 Changed 6 years ago by jokeyrhyme

Here's an example of what I'm talking about: http://jsfiddle.net/fQLum/

The first function is how everyone would be using Deferreds right now.

The second function is how I am currently using Deferreds, to improve my UI responsiveness. It would be terrific if I didn't have to do the setTimeout myself, but if were done automatically inside the Deferred.

I understand perfectly if this suggestion is rejected. I am just throwing it out there in case this idea is something others will find useful. It might be that this technique can be married with Deferreds in someway that does not effect the core Deferred implementation but is still transparent enough to be terrific short-hand.

comment:4 Changed 6 years ago by gnarf

setTimeout( fn, 0 ) is not "immediate". Take a look at this article.

I see why in your use case you would like for the processing to happen inside of its own event loop, but this is a situation where you could easily write your own wrapper for $.Deferred that injects the logic you need to the specific deferreds you want to "enhance".

I think adding any setTimeout inbetween resolve and done is unnecessary for >90% of its uses and much better to be solved by your own wrapper, something like this fiddle.

comment:5 Changed 6 years ago by ajpiano

Component: unfileddeferred
Resolution: wontfix
Status: newclosed

"I think adding any setTimeout inbetween resolve and done is unnecessary for >90% of its uses and much better to be solved by your own wrapper, something like this fiddle."


Last edited 6 years ago by ajpiano (previous) (diff)

comment:6 Changed 6 years ago by dmethvin

This really does seem like a job for web workers and postMessage, although you'll need a shim for older browsers like IE if you need to support them.

I would not expect the jQuery API to visibly change for developers.

Those are the _worst_ kind of changes, when the semantics are altered in a new version but the syntax stays the same. Adding setTimeout changes a synchronous operation to an asynchronous one.

comment:7 Changed 6 years ago by jaubourg

To be honest, I would have loved to be able to implement resolveWith that way, it would have solved all our try/finally and dead-locking in IE problems.

Sadly, since ajax can be ran synchronously, it just wasn't an option :/

Note: See TracTickets for help on using tickets.