async-awaitの落とし穴(と解決策)

さて問題です。

以下のようなコードがあります。

```ts

async allTask() {
     let task1Results = await task1();
     await task2();
     task1Results.map(async result => task3(result));
}
```

こちらとしてはtask1とtask2とtask3が逐次的に実行してくれることを期待していますが、
コレはそのように仕事をしてくれるのでしょうか？

してくれませんでした。 ``task1Results.map(async result => task3(result));``が
task2を待たずに非同期で実行されてしまいます。

```ts
async allTask() {
     let task1Results = await task1();
     await task2();
     await Promise.all(task1Results.map(async result => task3(result)));
}
```
ちゃんと ``await promise.all``をつけないとだめです。気づかなくて2h消費しました


# だめな例

```ts

async function sleep(time: number) {
    return new Promise<void>(resolve => {
      setTimeout(() => (resolve()), time);
    });
  }
  
  
  async function task1() {
    await sleep(1000);
    console.log(`task1 end`);
    return new AsyncArray(0,1,2,3,4,5);
  }
  
  async function task2() {
    await sleep(3000)
    console.log(`task2 end`);
  }
  
  async function task3(num:number) {
    await sleep(num * 1000);
    console.log(`task3(${num}) end`);
  }
  
  async function allTask() {
    let results =  await task1();
    await task2();
    await results.asyncMap(async num => task3(num));
  }
  
  allTask().then(() => console.log('allTask end'));
  
```

```js:output
task1 end
task2 end
allTask end
task3(0) end
task3(1) end
task3(2) end
task3(3) end
task3(4) end
task3(5) end
```

# 改善1

```ts
async function sleep(time: number) {
    return new Promise<void>(resolve => {
      setTimeout(() => (resolve()), time);
    });
  }
  
  
  async function task1(): Promise<number[]> {
    await sleep(1000);
    console.log(`task1 end`);
    return [0,1,2,3,4,5];
  }
  
  async function task2() {
    await sleep(3000)
    console.log(`task2 end`);
  }
  
  async function task3(num:number) {
    await sleep(num * 1000);
    console.log(`task3(${num}) end`);
  }
  
  async function allTask() {
    let results =  await task1();
    await task2();
    await Promise.all(results.map(async num => task3(num)));
  }
  
  allTask().then(() => console.log('allTask end'));
  
```


```js:output
task1 end
task2 end
task3(0) end
task3(1) end
task3(2) end
task3(3) end
task3(4) end
task3(5) end
allTask end
```

# 改善2

```
export class AsyncArray<T> extends Array<T> {
    async asyncFilter(compare: (value: T) => Promise<boolean>) {
      const results = await Promise.all(this.map(v => compare(v)));
      return <AsyncArray<T>>this.filter((_, i) => results[i]);
    }
  
    async asyncMap<U>(convert: (value: T) => Promise<U>) {
      return <Array<U>> await Promise.all(this.map(convert));
    }
  }
  
  async function sleep(time: number) {
    return new Promise<void>(resolve => {
      setTimeout(() => (resolve()), time);
    });
  }
  
  
  async function task1() {
    await sleep(1000);
    console.log(`task1 end`);
    return new AsyncArray(0,1,2,3,4,5);
  }
  
  async function task2() {
    await sleep(3000)
    console.log(`task2 end`);
  }
  
  async function task3(num:number) {
    await sleep(num * 1000);
    console.log(`task3(${num}) end`);
  }
  
  async function allTask() {
    let results =  await task1();
    await task2();
    await results.asyncMap(async num => task3(num));
  }
  
  allTask().then(() => console.log('allTask end'));
  
```

```js:output
task1 end
task2 end
task3(0) end
task3(1) end
task3(2) end
task3(3) end
task3(4) end
task3(5) end
allTask end
```