Synchronet v3.19b-Win32 (install) has been released (Jan-2022).

You can donate to the Synchronet project using PayPal.

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
custom:javascript:callbacks [2021/04/04 20:33] – [The Event Loop] Deucecustom:javascript:callbacks [2021/04/05 12:49] (current) – [Callback API] Deuce
Line 6: Line 6:
  
 **callback**\\ **callback**\\
-a callback is simply a function passed as an argument with the expectation that it will be called when specific conditions are met.+a callback is simply a function passed as an argument with the expectation that it will be invoked when specific conditions are met.
  
 **polled callbacks**\\ **polled callbacks**\\
-polled callbacks are those that will be called if no script is currently running, and the triggering condition is present.+polled callbacks are those that will be invoked if no script is currently running, and the triggering condition is present.
  
 **timer callbacks**\\ timer callbacks are invoked after a defined period of time. **timer callbacks**\\ timer callbacks are invoked after a defined period of time.
Line 36: Line 36:
  
 ''js.addEventListener(eventName, callback)'' (returns an ID)\\ ''js.addEventListener(eventName, callback)'' (returns an ID)\\
-Installs a callback for the string ''eventName''.+Installs a user callback for the string ''eventName''.  ''eventName'' is any string defined by the programmer.  Care should be taken to ensure the string is unique to the use case and not generic to avoid conflicting with other libraries.
  
 ''js.dispatchEvent(eventName[, thisObj])''\\ ''js.dispatchEvent(eventName[, thisObj])''\\
-Adds all callbacks which were installed with the specified ''eventName'' to the run queue.+Adds all user callbacks which were installed with the specified ''eventName'' to the run queue.
  
 ''js.setImmediate(callback[, thisObj])''\\ ''js.setImmediate(callback[, thisObj])''\\
Line 50: Line 50:
 Clears a callback installed via js.setTimeout() Clears a callback installed via js.setTimeout()
  
-''js.removeEventListener(id)''\\ +''js.removeEventListener(id_or_name)''\\ 
-Removes a callback installed via js.addEventListener()+Removes callbacks installed via js.addEventListener().  If ''id_or_name'' is the value returned by js.addEventListener(), only a single listener is removed.  If ''is_or_name'' is a string, all listeners for that eventName will be cleared.
  
 The following methods are available to instances of the Socket class.  They will use ''sock'' as the name of the instance.  Note that a closed socket can be read without blocking when it has been closed.  This means that any socket callback that triggers when the socket can be read should check if the socket has been closed before returning to prevent an infinite loop.  The ''this'' object in the invocation will be the Socket instance itself.  Additional properties can be added to the Socket object to pass additional state to/from the callback. The following methods are available to instances of the Socket class.  They will use ''sock'' as the name of the instance.  Note that a closed socket can be read without blocking when it has been closed.  This means that any socket callback that triggers when the socket can be read should check if the socket has been closed before returning to prevent an infinite loop.  The ''this'' object in the invocation will be the Socket instance itself.  Additional properties can be added to the Socket object to pass additional state to/from the callback.
Line 67: Line 67:
 Clears a callback installed via sock.on().  The ''op'' parameter must match the one passed to sock.on(). Clears a callback installed via sock.on().  The ''op'' parameter must match the one passed to sock.on().
  
-''sock.clearOnce(op, id)''+''sock.clearOnce(op, id)''\\
 Clears a callback installed via sock.once().  The ''op'' parameter must match the one passed to sock.once(). Clears a callback installed via sock.once().  The ''op'' parameter must match the one passed to sock.once().
  
Line 89: Line 89:
  
 The event loops is ran after the script finishes executing while js.do_callbacks is set and there are either timer or polled callbacks installed, or there are any items in the run queue.  The event loop will first check for if any polled callbacks need to be invoked.  If they is any, one will be chosen and invoked, and the event loop will restart after it completes.  If there are no polled events to invoke, timers are checked next.  If any timer is pending, one will be invoked, and the event loop will restart after it completes.  Finally, if there were no polled or timer callbacks to invoke, the oldest callback on the run queue is invoked. The event loops is ran after the script finishes executing while js.do_callbacks is set and there are either timer or polled callbacks installed, or there are any items in the run queue.  The event loop will first check for if any polled callbacks need to be invoked.  If they is any, one will be chosen and invoked, and the event loop will restart after it completes.  If there are no polled events to invoke, timers are checked next.  If any timer is pending, one will be invoked, and the event loop will restart after it completes.  Finally, if there were no polled or timer callbacks to invoke, the oldest callback on the run queue is invoked.
 +
 +Note that since polled callbacks are triggered based on current state, only one will be triggered for each such state.  If the callback does not clear the state (ie: by calling sock.recv()) it will be invoked again next time through the event loop.  If it does clear the state, no callbacks will be invoked in the next pass through the event loop.  This does not impact timers because each timer has a separate base time, so there will never be two timer callbacks for the same state.
  
 Basically: Basically:
 <code javascript> <code javascript>
 while (js.do_callbacks && (timer_callback_count > 0 || polled_callback_count > 0 || run_queue.length > 0)) { while (js.do_callbacks && (timer_callback_count > 0 || polled_callback_count > 0 || run_queue.length > 0)) {
-        if (polled_callback_ready) {+        timeout = time_to_next_timed_event; 
 +        if (run_queue.length > 0) 
 +                timeout = 0; 
 +        poll_result = poll_callback_states(timeout); 
 +        if (poll_result.polled_callback_ready) {
                 polled_callback.call(thisObj);                 polled_callback.call(thisObj);
                 continue;                 continue;
         }         }
-        if (timed_callback_ready) {+        if (poll_result.timed_callback_ready) {
                 timed_callback.call(thisObj);                 timed_callback.call(thisObj);
                 continue;                 continue;
         }         }
-        if (run_queue.length > 0) { +        if (poll_result.run_queue.length > 0) { 
-                polled_callback.shift().call(thisObj);+                run_queue.shift().call(thisObj);
                 continue;                 continue;
         }         }