Trying to write the flow logic for a drawing tool where user can enter a combination of keyboard inputs to draw complicated shapes on a canvas, to achieve this I’m trying to chain event listeners in a way that they remove themselves once done keeping global state clean. I would rather do this than keeping track hundreds of global state variabls that manages which listeners are active etc. I’m making progress but I’m stuck on recusive calls to Promise.race
not sure if there’s a better way to achieve this.
Using Promise.race in a recusive loop means that alot of the promises do not get resolved.
Is there a better way for me to do this?
function startCount(node) {
const counter = Object.create(counterMethods);
counter.node = node;
counter.number = 0;
counter.exitloopflag = false;
return counter;
}
const counterMethods = {
doCounter: function () {
return new Promise((resolve) => {
let handler = () => {
this.node.removeEventListener("click", handler);
console.log("lip");
resolve("click");
};
this.node.addEventListener("click", handler);
});
},
quit: function () {
return new Promise((resolve) => {
let handler = (e) => {
if (e.key === "Escape") {
this.node.removeEventListener("keydown", handler);
console.log("lap");
resolve("exit");
}
};
this.node.addEventListener("keydown", handler);
});
},
counterFlow: async function () {
//if (this.exit) return;
let result = await Promise.race([this.doCounter(), this.quit()]);
if (result === "exit") {
console.log(`You have pressed exit`);
// this.exit = true;
} else if (result === "click") {
this.number += 1;
console.log(`You have clicked ${this.number} of times`);
this.counterFlow();
} else {
console.log("code should not have run here");
}
},
};
2
Answers
I don't think there's an easy way to do this after all, I've resorted to using signals to abort the listeners not sure if this is in efficient but it does seem to work. Also in the mean time I learn how classes work so I've may have updated the code a little. Previously when I press "esc" I get "clack" console.logged out for as many times as I have clicked i.e. build up of exit event listerners from Promise.race however i've used a abort signal to turn those off every time now.
I do not think that a recursive approach is necessary at all, but this is hard to say for certain because it is unclear what you want to achieve with it. Since you speak of a drawing tool, I assume that you want to prevent the handling of certain events depending on which event came before.
For example, an event that starts a drawing must be followed by another that finishes the drawing (or by the "Escape" button), but not by another "start drawing" event. This can be achieved with event handlers that are added only once, but whose behavior depends on a
state
variable.The following snippet illustrates this: Clicking, dragging and releasing the mouse draws a rectangle with the start and end points as diagonally opposite corners. But pressing "Escape" during the dragging cancels the drawing.
The number of possible
state
s can be much bigger, of course. From the example you gave for drawing a rectangle, I can imagine the following:A polygon can then be drawn as follows: The first line is established by the first two clicks, subsequent lines by one more click each, until escape is pressed.