Both sides previous revisionPrevious revisionNext revision | Previous revision |
custom:javascript:callbacks [2021/04/04 20:35] – [Callback API] Deuce | custom:javascript:callbacks [2021/04/05 12:49] (current) – [Callback API] Deuce |
---|
| |
**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. |
| |
''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])''\\ |
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. |
| |
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; |
} | } |