Processing tasks as they are completed

I was reading some Python code and really like the signature of asyncio.as_completed(). It returns an iterable of tasks that you can await. What’s really nice about this is that it’s very intuitive. The first task that you await is the first task that completes.

I’ve decided to implement a version of it in typescript.

Setup

We want a way to generate a list of async tasks with random delays. The following should do that

Debounce requests to server

I recently got asked to implement a toy problem where there’s a autocompletion input box. As users enter a keyword in the box, the client would make a request to server to get back a list of suggestions to render.

Normally I would use deferred value to make the application responsive, like so

export default function App() {
  const [keyword, setKeyword] = useState("");
  const deferredKeyword = useDeferredValue(keyword);

  function handleKeywordChange(e: React.ChangeEvent<HTMLInputElement>) {
    setKeyword(e.target.value);
  }

  return (
    <div className="App">
      <label>
        Search: <input value={keyword} onChange={handleKeywordChange} />
      </label>
      <SearchResults query={deferredKeyword} />
    </div>
  );
}

Using deferred value allows React to rerender the component in background, and if there’s a new re-render, the previous render will be discarded.

Smooth rendering of streaming text content

I recently built a toy app that subscribes to a stream of text content and renders the content as it’s being delivered . The first approach I tried was to use a state and append chunks to the state as they come in.

const [text, setText] = useState('');

// inside an event handler
subscribe((chunk) => {
    setText(text => text + chunk);
});

// rendering
<pre> {text} </pre>

This works, but the rendering is not smooth. The text appears to come in “bursts”, because of server latency and different sizes of the chunks. It would look smooth if the latency when delivering each chunk is the same and the chunk is just one character.

React 19 - useOptimistic

This New hook: useOptimistic gives an example of how useOptimistic is used

const [optimisticName, setOptimisticName] = useOptimistic(currentName);

const submitAction = async formData => {
    const newName = formData.get("name");
    setOptimisticName(newName);
    const updatedName = await updateName(newName);
    onUpdateName(updatedName);
};

and it states

The useOptimistic hook will immediately render the optimisticName while the updateName request is in progress. When the update finishes or errors, React will automatically switch back to the currentName value.

It was confusing to me. If optimisticName just switches back to the currentName after the current async operation finishes then there must be another state to save the updated value. However the template code only uses one state - optimisticName.

Slicing strings in JS

When I need to get a substring, I usually use one of the following two methods: substring and substr. One thing that really bothers me is that the names of these functions are so similar that I almost always have to look them up.

Today, I accidentally wrote string.slice() in an app because I had just been coding in Python. To my surprise, it worked! I didn’t know you could slice a string and get back a string in JavaScript, just like in Python. I’ve been programming for 15 years and using JavaScript for almost that long, but I wasn’t aware of this. Oof!

Safari Extensions

List of safari extensions I’ve created:

App Store Description
Download on the Apple Store
Adds fuzzy search function to help you find tabs quickly, even when you can’t quite remember the exact title
Download on the Apple Store
Automatically identifies and closes duplicate tabs, putting an end to unintentional tab duplication
Download on the Apple Store
Simply opens Linkding page with your URL pre-populated. It also provides an Options page where you can customize your linkding server address
Download on the Apple Store
Configures which websites to redirect using plain URLs or, for advanced users, regular expressions. When a match is found, the page will automatically be redirected to your chosen destination
Download on the Apple Store
Translates current page with Google Translate with just one click (or Command + Shift + O shortcut)
Download on the Apple Store
Simple extension to copy URL in plaintext or markdown format to clipboard.
Download on the Apple Store
Discover external links on web pages with copy urls option
Download on the Apple Store
Quickly find tabs based on page content

Yet Another Word Based Suggestions extension for vscode

TLDR: https://github.com/tuan/yaws

So I’ve been using Vscode’s Neovim extension for a while. This extension is, IMO, integrated better with VIM (or NeoVim to be exact) that the other VscodeVim extension. But lately, the neovim extension has been having problem with buffer synchronization, i.e. the vscode’s buffer and neovim’s buffer get out of sync. I’m not sure what the root cause is. It’s probably caused by conflicts or race conditions among multiple extensions that all try to update text editors at the same time, e.g. linters, formatters, and neovim. I however cannot reliably reproduce the issue.

Unpoly Notes

Last weekend I spent some time playing with HTMX and created this app. While HTMX significantly simplifies the server and client interactions, for example I no longer need to create separate REST APIs to serve the client, but I feel like the DevX is not great. There are 2 things I had to deal with while working on that simple vacabulary app are:

1 - No REST API endpoints needed, but new endpoints to return partial HTMLs are needed. Technically, you can just reuse the existing endpoint, and conditionally return partial HTMLs, but I consider both approaches are pretty much the same in terms of engineering cost.

The joy of using simple tools

I’ve been building a few toy projects. After leaving my previous job, I miss all the nice fancy DevOps systems or pipelines that I previously had, for example monitoring and CI/CD. So I looked around to see if I can find OSS alternatives. The good thing is that there are plenty out there, but the bad thing is that they are way too complicated for the kind of toy projects that I’m building. After wasting too much time on learning about these fancy offerings on the market, configuring them, and making them work together, I’ve decided that it’s not worth the effort and are overkill for simple projects. So now I just use simple CLI tools to accomplish my tasks. And I’ve beeing enjoying the simplified setup a lot!

HTMX Newbie's Notes

Not sure which bubble I’m currently in now, but for some reasons I have heard a lot about HTMX lately. I’ve decided to build something with HTMX to see what it actually feels like in practice.

The project is a simple page that allows users to look up a word and quickly add it to Anki, a flashcard program. The current working prototype is https://vocab.tentativeknowledge.com. The adding note to Anki feature currently only works on desktop and depends on AnkiConnect add-on.