3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptには Promise という非同期処理のための仕組みがありますが、
通常のPromiseはresolve/rejectをPromiseコンストラクタの中でしか呼べないという制約があります。

ですが、Supabaseのコードベースではそれを柔軟に扱うために、Deferred クラスという仕組みが使われています。


Deferredクラスの実装

export class Deferred<T = any> {
  public static promiseConstructor: PromiseConstructor = Promise

  public readonly promise!: PromiseLike<T>
  public readonly resolve!: (value?: T | PromiseLike<T>) => void
  public readonly reject!: (reason?: any) => any

  public constructor() {
    ;(this as any).promise = new Deferred.promiseConstructor((res, rej) => {
      ;(this as any).resolve = res
      ;(this as any).reject = rej
    })
  }
}

何が嬉しいのか?

通常の Promise の使い方はこうです:

const promise = new Promise((resolve, reject) => {
  setTimeout(() => resolve("done"), 1000)
})

この場合、resolve/rejectを外部から呼ぶことはできません。

一方で Deferred を使うと、後から明示的に resolve や reject を呼び出すことが可能になります:

const deferred = new Deferred<string>()

setTimeout(() => {
  deferred.resolve("OK!") // 外からresolveできる!
}, 1000)

await deferred.promise // => "OK!"

なぜ便利なのか?

Deferredパターンは以下のような場面で非常に役立ちます:

  • コールバックベースのAPIをPromiseに変換したいとき

  • 複数イベントの完了を待ちたいとき

  • 一度だけ解決されるフラグ的な非同期処理が欲しいとき(例:ロックの開放)

  • await で外から制御可能なPromiseを生成したいとき

Supabaseでの利用例

SupabaseのSDKでは、ロック機構や状態遷移の管理、非同期イベントの通知など、
Promiseの解決タイミングを後回しにする必要がある場面でこの Deferred が使われています。

まとめ

  • Deferred は Promise をより柔軟に制御するための仕組み
  • resolve() や reject() を 外部から呼べる
  • Supabaseのような高機能ライブラリでは非同期制御の要となっている

参考リンク

3
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?