Skip to content

[BUG] Listeners seem to not act on events sometimes #2702

@thyttan

Description

@thyttan

Background

The widgets widbtstates and widbt_notify have/had problems where the connection state change did not trigger a redraw of the widget. Making it so the widget could be out of sync with the actual state. I.e. showing disconnected while the watch is actually connected and vice versa. Making me suspicious something is breaking the emit/listener chain.

Recently something similar cropped up for the drained app as well. It seemed its listener function for the charging event would not run when charging was initiated thus not setting a interval that's supposed to return the watch to normal operations when the charge goes above a threshold.

drained: handle missed "changing" events #4188
widbtstates: sync on draw() #4141
widbt_notify: redraw widget on NRF dis-/connect #3735

Possibly related other issues:
removeListener while executing events stops subsequent listeners from executing #2151
Obj.on/emit should always allocate an array #2559

Test script

I've run the following test script with a TEST_COUNT of 500 and have not seen it miss events tested this way.

 // Script to try and see if acting on events are sometimes missed.

let obj = {};
let i=0;
const TEST_COUNT = 10;
let last_e = -1;
let isEventsMissed = false;
const PRINT_EVERY_EVENT = true;

obj.on("test", (e, type)=>{
  if (PRINT_EVERY_EVENT) print("acting on test event " + e + " ("+type+")");
  if (e !== last_e+1) {
    print("\n missed events before event " + e);
    isEventsMissed = true;
  }
  last_e = e;
});

print("\n test in for loop started:");

for (i;i<TEST_COUNT;i++) {
  if (PRINT_EVERY_EVENT) print("emitting test event " + i);
  obj.emit("test", i, "for-loop");
}

setTimeout(()=>{
  print("\n\n test in interval started:");
  let interval = setInterval(()=>{
    if (PRINT_EVERY_EVENT) print("emitting test event " + i);
    obj.emit("test", i, "interval");
    i++;
    if (i > 2*TEST_COUNT-1) {
      clearInterval(interval);
    }
  },0);

},0);

setTimeout(()=>{
  if (isEventsMissed) {
    print("\nSeems like some events were missed");
  } else {
    print("\nSeems like no events were missed");
  }
},1000);

/* Resulting output running from storage:

 ____                 _
|  __|___ ___ ___ _ _|_|___ ___
|  __|_ -| . |  _| | | |   | . |
|____|___|  _|_| |___|_|_|_|___|
         |_| espruino.com
 2v29.26 (c) 2025 G.Williams

 test in for loop started:
emitting test event 0
emitting test event 1
emitting test event 2
emitting test event 3
emitting test event 4
emitting test event 5
emitting test event 6
emitting test event 7
emitting test event 8
emitting test event 9


 test in interval started:
acting on test event 0 (for-loop)
acting on test event 1 (for-loop)
acting on test event 2 (for-loop)
acting on test event 3 (for-loop)
acting on test event 4 (for-loop)
acting on test event 5 (for-loop)
acting on test event 6 (for-loop)
acting on test event 7 (for-loop)
acting on test event 8 (for-loop)
acting on test event 9 (for-loop)
emitting test event 10
acting on test event 10 (interval)
emitting test event 11
acting on test event 11 (interval)
emitting test event 12
acting on test event 12 (interval)
emitting test event 13
acting on test event 13 (interval)
emitting test event 14
acting on test event 14 (interval)
emitting test event 15
acting on test event 15 (interval)
emitting test event 16
acting on test event 16 (interval)
emitting test event 17
acting on test event 17 (interval)
emitting test event 18
acting on test event 18 (interval)
emitting test event 19
acting on test event 19 (interval)

Seems like no events were missed
>

*/

/* Resulting output running from RAM:

 ____                 _
|  __|___ ___ ___ _ _|_|___ ___
|  __|_ -| . |  _| | | |   | . |
|____|___|  _|_| |___|_|_|_|___|
         |_| espruino.com
 2v29.26 (c) 2025 G.Williams
>

 test in for loop started:
emitting test event 0
emitting test event 1
emitting test event 2
emitting test event 3
emitting test event 4
emitting test event 5
emitting test event 6
emitting test event 7
emitting test event 8
emitting test event 9
acting on test event 0 (for-loop)
acting on test event 1 (for-loop)
acting on test event 2 (for-loop)
acting on test event 3 (for-loop)
acting on test event 4 (for-loop)
acting on test event 5 (for-loop)
acting on test event 6 (for-loop)
acting on test event 7 (for-loop)
acting on test event 8 (for-loop)
acting on test event 9 (for-loop)


 test in interval started:
emitting test event 10
acting on test event 10 (interval)
emitting test event 11
acting on test event 11 (interval)
emitting test event 12
acting on test event 12 (interval)
emitting test event 13
acting on test event 13 (interval)
emitting test event 14
acting on test event 14 (interval)
emitting test event 15
acting on test event 15 (interval)
emitting test event 16
acting on test event 16 (interval)
emitting test event 17
acting on test event 17 (interval)
emitting test event 18
acting on test event 18 (interval)
emitting test event 19
acting on test event 19 (interval)

Seems like no events were missed
> 

*/

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions