各イベントループにはマイクロタスクキューがあり、これはキュー内のマイクロタスクの集合体で、初期状態では空です。マイクロタスクとは、キューにマイクロタスクを追加するアルゴリズムによって生成されたタスクを指す俗語です。

✅ “drain” の意味
上の仕様に続いて、microtask queue の処理は以下のように扱われます:
microtask checkpoint では、microtask queue に入っているものをすべて処理する
その処理中にさらに microtask がキューに追加されても、そのまま同じ checkpoint で実行される
microtask queue が 完全に空になるまで処理が続く
この挙動はブラウザの実装文脈でも説明されており、たとえば次のように解説されています:
after each task exits, the event loop runs all of the pending microtasks until the queue is empty
(タスクが終わるとイベントループは キューが空になるまで 保留中の microtask をすべて実行する)MDN Web Docs
また日本語の解説でも:
Call Stack が空になった直後、Microtask Queue を確認し、キューが空になるまで一つずつ順番に実行する
(この実行中にさらに microtask が追加されれば、それも同じタイミングで実行される)Zenn
この “queue が 完全に empty になるまで” という部分が、よく言われる「drain」の意味です。
console.log("start");
queueMicrotask(() => console.log("microtask 1"));
Promise.resolve().then(() => console.log("microtask 2"));
console.log("end");
setTimeout(() => console.log("macrotask"), 0);

解説(何が起きている?)
同期処理 console.log("start") → 実行
queueMicrotask → microtask キューに積まれる
Promise.then → microtask キューに積まれる
同期処理 console.log("end") → 実行
コールスタックが空になったので microtask checkpoint が起きる
→ キューの microtask を すべて実行(これが drain)microtask が空になったので task(setTimeout)が実行される
この順序から分かるように、
👉 microtask は 1 個だけではなく、キューが完全に空になるまで順番にすべて実行される
👉 そして その後に macrotask(ここでは setTimeout)に進む
という挙動になっています。これが「drain」です。