• I like you're having fun with Espruino...

    I wondered about the comma (,) in line 17 of first code block: Does it not show error in Espruino Web IDE?

    In order to go fully through with Javascript's prototype idea (including the methods), the code may look like below. With methods on prototype - class definition represented by constructor (function) - (each) method exists only once. If the method is assigned with a definition in the constructor, the methods, such as .doCount() exist actually multiple times - once for each of the object instances. To take advantage of object-oriented encapsulation even further, adding .start() and .stop() (and private ._stop()) and .log()` methods simplifies the use and saves also some more space...

    function TestObj(name, mCount, interval) {
      this.name = name;
      this.mCount = mCount;
      this.count = 0;
      this.interval = interval;
      this.id = null;
    } // end testObj - constructor (and state setting)
    // Method definition(s):
    TestObj.prototype.doCount = function() {
      this.count++;
      this.log(this.count);
      if (this.count >= this.mCount) {
        this._stop("");
      } // endif
    }; // end doCount() method of TextObj
    TestObj.prototype.stop = function() {
      this._stop("was ");
    };
    TestObj.prototype.start = function() {
      if (this.id) {
        this.log("already started and is 'running'");
      } else {
        this.count = 0;
        this.id = setInterval( this.doCount.bind(this)
                             , this.interval );
        this.log("started");
      }
    };
    TestObj.prototype._stop = function(reason) {
      if (this.id) {
        clearInterval(this.id);
        this.id = null;
        this.log(reason + "stopped");
      } else {
        this.log("not 'running' (yet or anymore)");
      }
    };
    TestObj.prototype.log = function(info) { 
      console.log(getTime(), this.name, " ", info);
    };
    
    // Test code
    var specs;
    function test() {             // --> t in 100[ms] (seq)
                                  //   10    20    30    40
        (specs =                  // ---|-----|-----|-----|
    [ [ null, "first" , 5,  500 ] // 5 10 15 20 25
    , [ null, "second", 4, 1000 ] //   10    20    30
    , [ null, "third" , 3, 1500 ] //      15       30
    , [ null, "fourth", 2, 2000 ] //         20          40
    ]   ).forEach(function(spec){
            (spec[0] = new TestObj(spec[1],spec[2],spec[3])
            ).start();
          });
    }
    setBusyIndicator(LED1);
    test();
    

    Notice the the Uppercase/lowercase conventions for Class name (Constructor), (state) properties (instance variables) and (behavior) properties (methods). It helps a lot to grasp quickly what's going on and helps with naming.

    Naming is always a struggle for me: id, interval, intervalId, intervalTime,... what is to pick? For example, this.id makes me think of the id of the object... but that may just be my (object-oriented) déformation professionelle... and it's (about) time (for me) to follow your role model: retire... ;-)

    You may also notice a difference in the .doCount(): since the function in setInterval() is executed at the end of the interval, there is no need to keep the object running for one more cycle to just discover that the object has to stop. Therefore, it can stop right away after the maximum count is both reached and printed in the console. Compare the two outputs below: first one was created with your original if-then-else code, and the second was produced with the print alway, fi-then-stop. Looking at and comparing the times - first thing on the line - helps).

     1v85 Copyright 2016 G.Williams
    >echo(0);
    949363502.26460552215 first   started
    949363502.26707267761 second   started
    949363502.26953887939 third   started
    949363502.27200794219 fourth   started
    =undefined
    949363502.76485729217 first   1
    949363503.26484680175 first   2
    949363503.26728725433 second   1
    949363503.76487255096 first   3
    949363503.76985359191 third   1
    949363504.26478481292 first   4
    949363504.26739025115 second   2
    949363504.27227306365 fourth   1
    949363504.76489257812 first   5
    949363505.26525497436 first   stopped
    949363505.26739025115 second   3
    949363505.26994323730 third   2
    949363506.26741886138 second   4
    949363506.27241039276 fourth   2
    949363506.76989746093 third   3
    949363507.26779460906 second   stopped
    949363508.27038764953 third   stopped
    949363508.27290058135 fourth   stopped
    >
    
     1v85 Copyright 2016 G.Williams
    >echo(0);
    949363622.59208297729 first   started
    949363622.59455299377 second   started
    949363622.59703159332 third   started
    949363622.59949874877 fourth   started
    =undefined
    949363623.09226894378 first   1
    949363623.59216308593 first   2
    949363623.59474182128 second   1
    949363624.09227466583 first   3
    949363624.09723472595 third   1
    949363624.59221839904 first   4
    949363624.59468936920 second   2
    949363624.59976100921 fourth   1
    949363625.09221076965 first   5
    949363625.09343433380 first   stopped
    949363625.59484004974 second   3
    949363625.59727954864 third   2
    949363626.59480190277 second   4
    949363626.59602737426 second   stopped
    949363626.59985637664 fourth   2
    949363626.60106182098 fourth   stopped
    949363627.09733486175 third   3
    949363627.09856033325 third   stopped
    >
    

    The log prints the time - first thing on the line - from where you can see that Espruino is pretty fast and keeps the intervals.. ;-). The time shows seconds.

    And last but not least notice the setBusyIndicator(LED1) in second to last line line 54: LED1 - the red on-board LED on classic and PICO Espruino boards - is on when Espruino is busy working... What you will notice is: Espruino is not really busy... ;-)... because it is fully event driven - also in the application code (as opposite to Arduino, which is always busy running the 'loop'). This is a major reason to chose Espruino over other and Arduino like implementations for standalone, battery operated, long-lasting applications.

    Provide a timing that keeps the interval end events separate, delivers a bit more interesting 'busy flicker' pattern (with the original timing, the interval ends fall within a 100st of a second... 0.01s, see console outputs above):

        (specs =                    // --> sequence: t in 100[ms]
    [ [ null, "first" , 5,  500 ] // 5 10  15  20    25
    , [ null, "second", 4, 1100 ] //     11      22      33 44
    , [ null, "third" , 3, 1600 ] //         16        32       48
    , [ null, "fourth", 2, 2300 ] //               23         46
    ]   ).forEach(function(spec){
    

    ...and with time to scale:

    // ----> t in 100[ms]
    //     10        20        30        40        50
    // '----|----'----+----'----|----'----+----'----+
    // 5   10   15   20   25
    //      11         22         33         44
    //           16              32              48
    //                  23                     46
    

    The setBusyIndicator() is useful to explain what is going on: You mention concurrently running objects... they are in regard of the life cycle of the intervals of the objects. In regard to the code: it is still sequential - one after the other. When a setTimeout() or setInterval() is executed, the related information is place in a (time drive) as work order in work queue and the application code comes to an end - you see this in the output where =undefined shows - and control is returned to the 'operating system' Espruino (firmware). Espruino then looks at this work queue, nothing is there to do, it switches off the pin specified in with setBusyIndicator() and goes to sleep - may be even deep sleep ( see sleep and setDeepsleep() and Power Consumption). When something has to be done right away or on timer / hardware interrupt, it switches the setBusyIndicator() pin on, picks up the work order and does specified work. Having set setBusyIndicator() and typing in the console shows that the console is actually managed by Espruino: every keystroke goes to Espruino and is accordingly processed - echoed back to the console pane in the browser...

    PS:

    
    
    

    specs[1][0]
    ={
    "name": "second",
    "mCount": 4, "count": 4, "interval": 1000, "id": null }

    
    ...and while it is running (with original timing): 
    
    

    949367054.10334491729 first 4
    949367054.10587024688 second 2
    949367054.11077404022 fourth 1
    specs[1][0]
    ={
    "name": "second",
    "mCount": 4, "count": 2, "interval": 1000, "id": 2 }
    949367054.60337352752 first 5
    949367054.60459995269 first stopped
    949367055.10592937469 second 3
    949367055.10837554931 third 2
    ```

About

Avatar for allObjects @allObjects started