1. ohgiwk

    Posted

    ohgiwk
Changes in title
+Async Await in Typescript
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,209 @@
+# はじめに
+
+最近、Typescirptを使い始めた若輩者ですが、もう型がないと息ができないくらいTypescriptに嵌まってしまいました。
+今回はTypescriptの機能の一つであるAsync/Awaitを紹介します。
+
+ES6にはPromiseがあり、非同期処理が非常に簡単に書けるようになりました。
+しかし、ECMAScriptはさらなる高みを目指しているみたいです。
+より発展的に非同期処理を記述できるようにするために、Async/Awaitを提案し、すでにstage3に入ってきています。
+
+Babelでは、`babel-preset-es2017` もしくは `babel-plugin-transform-async-to-generator`を利用することで使用することができるみたいです。
+
+ECMAScriptのSupersetであるTypescriptも、Async/Awaitをサポートしています。(v1.6~)
+
+Promiseによって、充分、非同期処理が簡単に書けるのですが、
+Async/Awaitはさらに簡略で、より慣れた手続き的な書き方で書けるようになります。
+
+
+
+### 動作環境
+Typescript v2.1.4
+
+### Async/Awaitのサポート
+
+今までは compilerOptionsの target を es6 に指定しないと、typescriptでAsync/Awaitをコンパイルできませんでした。
+そのため、ブラウザ環境向けに利用するには、TypescirptからES6にコンパイルして、さらにBabelでトランスパイルするような過程が必要だったりしたですが、v2.1より es5/es3に指定してもコンパイルできるようになりました。
+これにより、より気軽にAsync/Awaitが使えるようになりましたね。
+
+[What's New TypeScript 2.1
+](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html)
+
+
+v1.6から `--experimentalAsyncFunctions`オプション付きでサポートを開始
+v1.7からオプションなし、"target": "es6" 限定でサポート
+v2.1から "target": "es5/es3"でサポート
+
+
+
+
+
+## 使ってみる
+
+2秒間待ってから "wait" と出力するwait関数を3回直列で実行するサンプルを書いてみます。
+
+まず、Promiseで書いてみます。
+
+```ts:promise.ts
+// Promiseを返す非同期関数
+function wait(): Promise<any> {
+ return new Promise(resolve => {
+ setTimeout(() => {
+ console.log('wait');
+ }, 2000);
+ })
+}
+
+function main() {
+ return wait()
+ .then(() => {
+ return wait();
+ })
+ .then(() => {
+ return wait();
+ });
+}
+
+main();
+
+```
+
+コールバックを用いた書き方よりはだいぶいいのですが、returnが多かったり、何度もthenをして、少し冗長な気がします。
+上記のmain関数をAsync/Awaitを用いた書き方で書き直してみます。
+
+```ts:async.ts
+
+// functionの前にasyncを書くとasync関数になります。
+async function main() {
+ await wait();
+ await wait();
+ await wait();
+}
+
+main();
+
+
+```
+
+
+.then()もなく、かなりスッキリした書き方になりました。
+
+このように、Async関数の中でPromiseを返す関数の前に`await`をつけるとその関数の処理が終わるまで待ってくれます。
+
+
+
+Async/Awaitはこのようなシンプルな記述をだけでなく、Promiseでは難しいより慣れた手続き的な表現ができます。
+
+Promiseでは処理の結果をresolve()でPromiseに包んで.then()のコールバック関数の引数として次の処理につなげることができますが、Async/Awaitを使えば、あたかも同期関数のように = で代入するような記述ができます。
+
+```ts
+//42がラップされたPromiseを返す関数
+function foo() {
+ return Promise.resolve(42);
+}
+
+
+function main() {
+ foo().then(num => {
+ console.log(num); //=> 42
+ });
+}
+main();
+
+async function main2() {
+ // あたかも普通の同期関数のように = で代入できる
+ const num = await foo();
+ console.log(num); //=> 42
+
+ // ちなみに型推論もちゃんとやってくれる
+ typeof(num) === 'number' //=> true
+}
+
+main2();
+
+```
+
+
+また、Promiseでのチェーンでは途中で処理を終了したい時などには.reject()して.catch()するなど工夫が必要です。
+
+しかし、Async/Awaitならば、通常の手続き処理のようにif文やswitch文、変数代入に利用できるので、自在に処理を切り分けたり、中断させることができます。
+
+```ts
+
+async function foo() {
+ // if文で使ったり
+ if (await model.exists()) {
+
+ }
+ // そのまま関数に渡したり
+ bar(await foo());
+
+ // 返り値の配列をそのまま参照
+ let result = (await bar())[0]
+}
+
+```
+
+
+async関数はそれ自体が何もしなくても自動的にPromiseを返すので、async関数の実行に続けて、.then()かawaitを書くことができます。
+
+```ts
+
+// Promiseを返すasync関数
+async foo() {
+ return wait();
+}
+
+// .then()で続ける
+foo().then(() => {
+ foo();
+});
+
+// awaitで待つ
+async main() {
+ await foo();
+}
+
+
+```
+
+いかがでしょうか。
+その他、Async/Awaitは様々なパターンの関数やメソッドに利用できます。
+
+```ts
+
+// アロー関数をAsync関数化
+async () => {
+ await this.foo();
+}
+
+
+// クラスのメソッドにもasyncが書ける
+class Foo {
+
+ async bar() {
+ await this.wait();
+ }
+
+ static async bar() {
+ await wait();
+ }
+}
+
+
+
+```
+
+
+
+とてつもなく簡単に非同期処理が書けるので、気持ちよくコードを書くことができます。
+
+ぜひ使ってみてください。
+
+
+
+参考
+[公式ドキュメント](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html)
+[JavaScriptは如何にしてAsync/Awaitを獲得したのか Qiita版](http://qiita.com/gaogao_9/items/5417d01b4641357900c7)
+
+
+