Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Callbacks implementation #265

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

Callbacks implementation #265

wants to merge 3 commits into from

Conversation

mmontone
Copy link
Contributor

@mmontone mmontone commented Feb 2, 2023

Hi,

I'm creating this pull request not so much for you to merge, but for discuss it, or discuss other options.
I think I may be stretching the limits of CLOG a bit, and so I need something like this. Or I'm wrong, and there's an alternative way of doing what I need with current CLOG already.

The issue is with the integration of some javascript components, where I need to execute some arbitrary javascript on the client, following some particular JS api, and at the same time bind some function server side.
So, I cannot use set-event family functions, I need to follow an api. And also I need to access arbitrary data sent from client side (and the data may be had to be extracted right from the client side event).

So I came up with this implementation of callbacks. Callback functions are defined via defcallback and then invoked from javascript via call-callback (call-callback actually generates the javascript needed to call the callback function).

For example, this is how I'm using it for a graph component I'm trying to integrate:

Define a callback function. args is an arbitrary json object sent from the client:

(clog-callbacks:defcallback graph-double-click (args)
  (let* ((node-id (car (access:access args :nodes)))
	 (obj (nth node-id *objects*)))
    (show obj)))

Generate js code following a js component api that calls the server-side callback and sends arbitrary js arguments to it:

(defun graph-set-on-double-click (graph stream)
  "Handle double click events for GRAPH."
  (format stream "~a.on('doubleClick', function (params) {
params.event = '[original event]';
~a
})"
	  (js-handle graph)
	  (clog-callbacks:call-callback 'graph-double-click "JSON.stringify(params)")))

Unfortunately the implementation needs to touch clog-connection::handle-message.
But let's discuss if possible.

Thank you.

@mmontone
Copy link
Contributor Author

mmontone commented Feb 3, 2023

Instead of defining a callback and then calling it, it is possible to do it at once just passing a lambda expression, and so the callback has access to the context in which it was created, something that is very needed, like this:

(defun graph-set-on-double-click (graph stream)
  "Handle double click events for GRAPH."
  (let ((callback-call (clog-callbacks:call-callback
			(lambda (args)
			  (let* ((node-id (car (access:access args :nodes))))
			    (show (find node-id (graph-nodes graph) :key #'car))))
			"JSON.stringify(params)"))
        (js-handle (js-handle graph)))
    (write-string
     (interpol
      "${js-handle}.on('doubleClick', function (params) {
        params.event = '[original event]';
        ${callback-call}
})")
     stream)))

@mmontone
Copy link
Contributor Author

mmontone commented Feb 3, 2023

One thought: if handle-message were extensible (replace the COND with a table dispatching that matches on the prefix message character). Like #\E for event. I could add #\C for callbacks to that table. And then I could plug this in without modifying Clog.

@rabbibotton
Copy link
Owner

I keep getting a bit delayed and flying for next 3 days. I will take a good look and give input soon.

It's very common to need to have callbacks as lambda expressions,
so that they have access to the context in which they are being
created.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants