Promise.resolve の使い所

resolved な Promise 返すよってだけ

The Promise.resolve() method returns a Promise object that is resolved with a given value. If the value is a promise, that promise is returned; if the value is a thenable (i.e. has a "then" method), the returned promise will "follow" that thenable, adopting its eventual state; otherwise the returned promise will be fulfilled with the value. This function flattens nested layers of promise-like objects (e.g. a promise that resolves to a promise that resolves to something) into a single layer.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve

いまいち使い道がわからなくて使ってなかったけど、今日ついに使い所に遭遇した。

example.ts
class {
  private _prop: string

  private async getProp() {
    if (this._prop) {
      const remoteResource = await API.fetch()
      this._prop = remoteResource.prop
    }
    return this._prop
  }

  doSomethingWithProp() {
    const propValue = await this.getProp()
    // using propValue ...
  }
}

非同期処理でとった結果をキャッシュして使うみたいな処理を書いてレビューお願いした

get て prefix 付いてるのに getter じゃないのなんで?って指摘を頂いて
納得感しかない

async getter はないので、<Promise> が返る getter にした

- private async getProp() {
-   if (this._prop) {
-     const remoteResource = await API.fetch()
-     this._prop = remoteResource.prop
-   }
-   return this._prop
- }
+ private get propPromise(): Promise<string> {
+   return this._prop
+     ? new Promise(resolve => resolve(this._prop))
+     : API.fetch().then(remoteResource => {
+         this.prop = remoteResource.prop
+         return this.prop
+       })
+ }

愚直に書き換えてこうなった

private get prop() でも良いかもしれないけど、
this.prop で常に新しい参照の <Promise> が返るのドキドキしすぎるので Promise って suffix つけた

ここで、(前々から思ってたんだけど) new Promise(resolve => resolve(this._prop))
ダサくない?ダサいよね?
もっと良い書き方あるでしょ、って MDNのPromiseのmethods ページ開いて

  private get propPromise(): Promise<string> {
    return this._prop
-     ? new Promise(resolve => resolve(this._prop))
+     ? Promise.resolve(this._prop)
      : API.fetch().then(remoteResource => {
          this.prop = remoteResource.prop
          return this.prop
        })
  }

あーーーーーーーーーー
ここかああーーーーーーーーーーーーーーーー Promise.resolve の使い所!!!!!!!

さらに、

(...) If the value is a promise, that promise is returned; if the value is a thenable (i.e. has a "then" method), the returned promise will "follow" that thenable, adopting its eventual state; otherwise the returned promise will be fulfilled with the value.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve

渡される値がなんだろうと 単一の flatな(nestしてない) Promise にする関数 なので、
Primitive な値 (この例では <string>) も <Promise<string>> も、もはや一緒に処理できる

なので Promise の Nest 気にせず いちいち三項演算しなくてよくてOK

  private get propPromise(): Promise<string> {
-    return this._prop
-     ? Promise.resolve(this._prop)
-     : API.fetch().then(remoteResource => {
+    return Promise.resolve(
+      this._prop ||
+      API.fetch().then(remoteResource => {
         this.prop = remoteResource.prop
         return this.prop
       })
+    )
  }

最終的にこうなった

example.ts
class {
  private _prop: string

  private get propPromise(): Promise<string> {
    return Promise.resolve(
      this._prop ||
        API.fetch().then(remoteResource => {
          this.prop = remoteResource.prop
          return this.prop
        })
    )
  }

  doSomethingWithProp() {
    const propValue = await this.propPromise
    // using propValue ...
  }
}

まあ何度見ても function call 以外から 新しい Promise 返るの慣れない