パルカワ2

PerlとRubyとイチャラブ

TypeScript の async/await

雰囲気でPromiseを使っていたが、雰囲気でTypeScriptを使い始め、雰囲気でasync/awaitを使い始めたが、よくわからないままだったので簡単に自分向けにまとめておく。 間違えていたら教えてほしい。ちなみにTSのtargetはes6

async をつけると

Promiseが返るようになるという認識

返り値

Promise.resolve() を返すかそのまま値を返すとよい。 Promise.resolve() が必要ないならわざわざラップして返す必要はなさそう。

 const t = async () => {
     return Promise.resolve("ok")
 };
 async function main() {
     await t().then(console.log);
     console.log("finish")
 }
 main();
 const t = async () => {
     return "ok"
 };
 async function main() {
     await t().then(console.log);
     console.log("finish")
 }
 main();
   const t = async () => {
       // returnしなくても次に進む
   };
   async function main() {
       await t().then(console.log);
       console.log("finish")
   }
   main();

エラーハンドリング

Promise.reject() を返すかthrowすればエラーが起きたことを知らせることが出来る。 try-catchを利用するので、エラーが起きた場合はthrowするのがわかりが良い気がする。

 const t = async () => {
     return Promise.reject(new Error("error!"))
 };
 async function main() {
     try {
       await t().then(console.log);
     } catch (error) {
         console.log("catch error", error)
     } finally {
       console.log("finish")
     }
 }
 main();
 const t = async () => {
     throw new Error("error!")
 };
 async function main() {
     try {
       await t().then(console.log);
     } catch (error) {
         console.log("catch error", error)
     } finally {
       console.log("finish")
     }
 }
 main();

また以下のようにthrowしただけであってもPromiseのcatchを使うことが可能である。 catchした場合は、try-catchのcatchには入らず、通常処理に戻る

  const t = async () => {
      throw new Error("error!")
  };
  async function main() {
      try {
        await t().catch(console.log)
        console.log("age") // 実行される
      } catch (error) {
          console.log("catch error", error)
      } finally {
        console.log("finish")
      }
  }
  main();

errorはなにも返さなくてもよい。 例えば Promise.reject() に何も渡さない場合catchされた error は undefined になる。エラーが起きたわけではないけど、なんらかの理由でこれ以上処理を進めたくない場合などに使うらしい。なるほど(Promiseのテクニック??)

 const t = async () => {
     return Promise.reject();
 };
 async function main() {
     try {
         await t()
         console.log("age") // 実行されない
     } catch (error) {
         console.log("catch error", error)
     } finally {
         console.log("finish")
     }
 }
 main();

個人的にはそれをやるならそれ用のエラーを作ったほうが明確でよいと思ったが好みかもしれない。

 class AbortError extends Error { 
 }
 const t = async () => {
     return Promise.reject(new AbortError("ほげほげだからAbortだよ"));
 };
 async function main() {
     try {
         await t()
         console.log("age")
     } catch (error) {
         if (error.constructor === AbortError) {
             console.log(error.message)
             return
         }
         console.log("catch error", error)
     } finally {
         console.log("finish")
     }
 }
 main();