Skip to content

Simpler Javascript communication #21

@geroldmeisinger

Description

@geroldmeisinger

based on https://github.com/chrisgoringe/Comfy-Custom-Node-How-To/wiki/Passing-control-to-javascript I wanted to know if there is a easier way to pass control to javascript without the hazzle of using proxies, routes and messageholder loops , if the javascript-side only runs synchronous code?

I stumbled upon: Comfy-Org/ComfyUI#2160
which would allow to write files to Comfy and maybe skip adding additional proxy routes and message holders.

GET /userdata/{file} gets a userdata file (or 404 if it doesnt exist)
POST /userdata/{file} writes a user data file with the post data

TODO:

  • i don't know how to get UserManager.get_request_user_filepath without a request
  • test interruption
  • does it work with multiple instances of the node? can multiple nodes even run concurrently?

in python:

from uuid import uuid4
from server import PromptServer
import os
import json
import time

nodename = "MyCustomNode"

...

	def execute(self, image):
		id = uuid4().hex
		path = f".../ComfyUI/user/default/{nodename}_{id}" # UserManager.get_request_user_filepath
		#print(path)

		with open(path, 'w') as file:
			file.write('{"status":"pending"}')

		message = { "id": id }
		PromptServer.instance.send_sync(nodename, message)

		status = "pending"
		with open(path, 'r') as file:
			while status == "pending":
				file.seek(0)
				content = file.read()
				#print(content)
				data = json.loads(content)
				status = data["status"]
				if status == "pending":
					time.sleep(0.1)
		os.unlink(path)

		if status != "done":
			raise Exception

		return (data["content"], )

in js:

import { app } from "../../scripts/app.js"
import { api } from "../../scripts/api.js"

const nodename = "MyCustomNode"
let id = ""

function on_execute(event)
{
	try
	{
		const { type, detail } = event
		console.log(JSON.stringify(event))

		id = detail.id
		api.fetchApi(`/userdata/${id}`,
		{
			method: "POST",
			headers: { "Content-Type": "application/json" },
			body: JSON.stringify({ status: "done", content: "Hello World" }),
		})
	}
	catch
	{
		cancel_execute("error")
	}
	finally
	{
		id = ""
	}
}

function on_execution_interrupted(event)
{
	cancel_execute("interrupted")
}

function cancel_execute(reason)
{
	if (id)
	{
		try
		{
			api.fetchApi(`/userdata/${id}`,
			{
				method: "POST",
				headers: { "Content-Type": "application/json" },
				body: JSON.stringify({ status: reason }),
			})
		}
		finally
		{
			id = ""
		}
	}
}

app.registerExtension(
{
	name: nodename,
	async setup()
	{
		api.addEventListener(nodename, on_execute)
		api.addEventListener("execution_interrupted", on_execution_interrupted)
	},
})

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions