🐙

google.script.run が Promise を返すようにする

2020/12/31に公開

期待を返せ

google.script.runwithSuccessHandlerwithFailureHandlerでコールバックを登録する仕様となっており、Promiseを返してくれません。
async/awaitですっきり書きたいですよね。

理想
(async ()=> {
  const data1 = await google.script.run.myFunction()
  const data2 = await google.script.run.myFunction2( data1 )
  console.log( data1 )
  console.log( data2 )
})();
現実
google.script.run
.withSuccessHandler( data1 => {
  google.script.run
  .withSuccessHandler( data2 => {
    console.log( data1 )
    console.log( data2 )
  })
  .withFailureHandler( console.error )
  .myFunction2( data1 )
})
.withFailureHandler( console.error )
.myFunction()

Promiseを返さないなら自作関数で包んでしまえ

というわけでgoogle.script.runを元にPromiseを返す関数を動的に定義します。

const ServerScript = {}
for ( const methodName in google.script.run ) {
  const method = google.script.run[ methodName ]
  if ( typeof method !== "function" ) continue
  if ( methodName === method.prototype.constructor.name ) continue
  ServerScript[ methodName ] = ( ...args ) => new Promise(
    ( resolve, reject ) => {
      google.script.run
      .withSuccessHandler( resolve )
      .withFailureHandler( reject )
      [ methodName ]( ...args )
    }
  )
}

(async ()=> {
  const data1 = await ServerScript.myFunction()
  const data2 = await ServerScript.myFunction2( data1 )
  console.log( data1 )
  console.log( data2 )
})()

for文の中の2つ目のifwithSuccessHandlerwithFailureHandlerを弾くためのものなので、別に無くても問題ないです。呼ばなければ良い話ですから。

また、この条件でもdoGetなどが入ってきてしまうのですが、呼んでもエラーなどは起きずに undefinedが返ってきます。元々のgoogle.script.runからそのような動きをするようなので、こちらも特に気にしないことにします。

以上、快適なGASライフを!

Discussion