Bug Tracker

Ticket #11470 (closed feature: fixed)

Opened 3 years ago

Last modified 2 years ago

Adding a builtin readyP promise

Reported by: bruant.d@… Owned by: jaubourg
Priority: low Milestone: 1.8
Component: core Version:
Keywords: Cc:
Blocking: Blocked by:

Description

Discussion with rick waldron [1] led to "Can you file a ticket: http://bugs.jquery.com so we can get a discussion going?" so here I am.

I've recently been teaching some JavaScript and some jQuery. I've also (less) recently discovered promises and just love how they work especially when it comes to synchronizing different async events with the $.when(promise1, promise2) construct.

An exercise I gave required to fetch an RSS feed, build a DOM fragment and append it to the DOM. In order to append something to the DOM, 2 things are required: 1) DOM is ready 2) RSS is retrieved This is a great opportunity to use $.when with 2 promises:


$.when($.get('rss.xml'), readyP).then(function(rss){

second argument purposefully ignored since I only care about synchronization

build a document fragment append to the document

});


Unfortunately, there is no readyP in jQuery, so I asked the students to add the following code before the $.when:


var readyDef = new $.Deferred(); var readyP = readyDef.promise(); $(function(){ readyDef.resolve() });


This really smells like boilerplate code to me. What about adding it to jQuery directly? Maybe defining a $.readyP? I have no strong opinion on what the resolution value could be. Maybe the document itself?

It has to be noted that some students did the following:


$(function(){

var rssP = $.get('rss.xml') rssP.then(function(rss){

build fragment append to DOM

})

});


It works, but the problem is that the xhr request isn't started before the document is ready (load event in old browser) which can be late. I think that having $.readyP included in the library would be a good incitation for both good programming style and performance at the same time.

Thanks

[1]  https://twitter.com/#!/rwaldron/status/179627982019764224

Change History

comment:1 Changed 3 years ago by bruant.d@…

Good grief! I didn't expect wiki formatting. Sorry for the poor rendering. Reorganized codes snippets:  https://gist.github.com/2030824

comment:2 Changed 3 years ago by fastfasterfastest

Or they could have done:

$.get('rss.xml').then(function(rss){
   $(function(){
      //build fragment append to DOM 
   });
});

Perhaps the document could expose its ready-ness as a promise, perhaps via the .promise method of a predefined type. Then:

$.when($.get('rss.xml'), $(document).promise('ready')).then(function(rss){ 
   //build fragment append to DOM 
}); 

comment:3 Changed 3 years ago by dmethvin

We used to have a promise in jQuery.ready but when it was refactored into jQuery.Callbacks that was removed. A promise would be more useful as an external interface though, wouldn't be hard to put it back if we wanted to.

Anybody else have thoughts? In an ideal world I'd put in the promise and remove the $(document).bind("ready", fn) fake event.

comment:4 Changed 3 years ago by jaubourg

I don't feel comfortable exposing the promise directly but I see value in a $.ready promise.

Just adding a promise method on top of the $.ready function could make for some nice looking code:

// In core
$.ready.promise = readyDeferred.promise;

// In user code
$.when( $.ready ).done(function() {
    // DOM IS READY
});

comment:5 Changed 3 years ago by sindresorhus

  • Priority changed from undecided to low
  • Component changed from unfiled to deferred

I've also needed this on multiple occasions and ended up doing the same thing as OP.

+1 for having a ready promise in core. @jaubourg's suggested syntax LGTM.

comment:6 Changed 2 years ago by dmethvin

  • Status changed from new to open
  • Milestone changed from None to 1.8

Let's do it. I like the syntax too.

comment:7 Changed 2 years ago by jaubourg

  • Owner set to jaubourg
  • Status changed from open to assigned

ok, I'm on it.

comment:8 Changed 2 years ago by jaubourg

  • Status changed from assigned to closed
  • Resolution set to fixed
  • Component changed from deferred to core
Note: See TracTickets for help on using tickets.