async-awaitでeventを同期的に書いてみる
ここで試してみるサイクル
1. 要素にマウスカーソルが入ったら
2. 650ms待ち
3. その間にカーソルがずっと要素の中にいたら色を変える
sample1.tsx/** @jsx h */
/** @jsxFrag Fragment */
import {h, Fragment, render} from "https://esm.sh/preact@10.5.14";
import {
useState, useEffect, useRef, useCallback
} from "https://esm.sh/preact@10.5.14/hooks";
const app = document.createElement("app");
const shadowRoot = app.attachShadow({mode: "open"});
const close = () => app.remove();
const App = () => {
const [message, setMessage] = useState("");
const ref = useRef<HTMLDivElement>(null);
const mouseDownPromise = useCallback(() => {
}, []);
useEffect(()=> {
while (true) {
}
}, []);
return (
<div className="container">
<button className="close" onClick={close}>x</button>
<div className="square" ref={ref} />
<span className="message">{message}</span>
</div>
);
};
const Style = () => <style>
.container {
position: absolute;
top: 10vh;
left 10vw;
}
.close {
display: block;
}
.square {
margin: 10px;
background-color: red;
}
.message {
display: block;
}
</style>;
render(<><Style /><App/ ></>, shadowRoot);
例えば mousedown
の発火を待つ函数は、単純に書くとこうなる
tsconst mouseDownPromise = useCallback(() => new Promise<MouseEvent>((resolve) => {
const callback = (e: MouseEvent)=> {
resolve(e);
ref.current.removeEventListener("mousedown", callback);
};
ref.current.addEventListener("mousedown", callback);
}), []);
const event = await mouseDownPromise();
// ...
しかしこれだと、何度も使うことが出来ない
一度だけしか mousedown
の発火を待てない
何度も使えるようにするには、毎回Promiseを作り直すよう設計を変える必要がある
だと思う。多分
