Difference between constructor and create

What's the difference between:

constructor: function () {
  console.log(this.$);
}

create: function(){
  console.log(this.$);
}
I found that, sometimes, not all components of a control could be initialized in constructor. Which means, console.log(this.$); of constructor is empty sometimes.

Comments

  • They are from slightly different points in the lifecycle. constructor is supported by any Enyo kind and is called first when the kind is created (either by new directly or implicitly when using features like the components block). create is introduced by enyo.Component and is called from constructed which is called immediately after constructor. The base implementation of create calls initComponents which creates the components declared in the components block of your kind. create, when overridden in subkinds, is usually responsible for any setup of controls after they are created but before they are rendered.

    Here's some pseudo-code that simplifies it all:
    // defined by the framework in Oop.js
    function enyoConstructor () {
        constructor();
        constructed();
    }
    
    // not often used by subkinds but can be
    // used to do pre-component setup
    function constructor () {}
    
    // more frequently seen for setup
    function constructed () {
        create();
    }
    
    // Component setup
    function create () {
        initComponents();
    }
    
    // Creates the child controls defined in components: []
    function initComponents () {}
    
  • This kind of stuff would be super handy to add to the docs, by the way.
  • We do have this document here: https://github.com/enyojs/enyo/wiki/Object-Lifecycle

    It seems it is not in the new developer guide though. I will see where we want to put this information or if it got inserted somewhere and I missed it.
  • Ah, I stand partially corrected, I just found part of it is in the key concepts of the developer guide:
    http://enyojs.com/docs/latest/developer-guide/key-concepts/components.html

    I still kinda like ryans' pseudo-code walkthrough though. It's compact and informative.

    By the way, considering the constructor is sometimes deferred, are there any other side-effects to executing things using the constructor or using the create method?
  • Ah, I should have poked harder to find that. I'll let Ryan respond on the constructor issue, but I don't believe so.
  • Deferred is going away with 2.6 but, even in 2.5 the constructor is called at the same time. The prototype creation is the 'thing' that is deferred and not the construction. When you call new, that's when the constructor method is called if the prototype was deferred or not.
  • edited July 2015
    Is there a way to hook into prototype creation? For instance, to create a debounced or throttled version of a method once, at prototype creation time rather than for each instance at construction time?
  • The config object you pass to enyo.kind is the most obvious option but I'm assuming there's something more complex about your question. Can you elaborate a bit on what you'd like to be able to do?
  • Well, there are multiple cases, but usually it's about methods that can get fired in rapid succession multiple times, while only the final state really matters.

    An example case is a UI where a user can cycle through a list of images and each new image animates into view. The user could rapidly push a 'next' button many times triggering many simultaneous animations, causing slow frame-rates in the process.

    What you could do instead is manipulate the currently selected index for each tap, but debounce the method that triggers new animations. This way, if a user taps 10 times in quick succession, they might only start 2 or 3 animations rather than 10, yet the final animation still brings them to the 10th next image.

    Currently, I simply create the all my methods the usual way, then pass it through a throttle method at construction time:
    enyo.kind({
      /**
      * Debounces myAction
      */
      create: enyo.inherit(function(sup) {
        return function() {
          sup.apply(this, arguments);
          this.myAction = _.throttle(this.myAction, 300);
        }
        // do stuff
      }),
    
      /**
      * Will be throttled at construction-time
      */
      myAction: function() {
        // do stuff
      }
    });
    This way, thanks to underscore's spiffy throttle function the method is throttled and I don't have to worry about handling context or anything like that. However, the original method does get replaced with a throttle version at instantiation time. It'd be cooler if I could get an already debounced method on the prototype.
  • edited July 2015
    Of course it'd be even cooler if enyo components include their own debounce utility, maybe something similar to what Polymer does. Their debouncing utilities include the ability to flush or cancel debounced jobs too, which is really, really useful as well.

    Which, by the way, if it sounds useful, I could try and create a mixin for that and make a pull-request.
  • The job API should give you much of what you need. The only thing it doesn't do it return the throttled/debounced function instead relying on names. This enables canceling the job but does result in slightly more cumbersome semantics. Here's a quick example:

    http://jsfiddle.net/3x8pugmd/
  • Interesting, I always thought that would result in 6 jobs :)
  • Ah, no. If you start a job with the same name, it cancels the prior timeout and starts anew. this.stopJob() will predictably stop the named job.
Sign In or Register to comment.