Lambda→DynamoDBが非同期処理と知らないやつがとった行動

### Alexaが人を返してくれない
DynamoDBからあるスキルに詳しい人の名前を取得してAlexaに返してもらおうとしている。DynamoDBへアクセスはできているが、なぜか人の名前を返してくれず、「さん」しか出てこない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/726018/3555bfe2-799d-1023-f4db-88362c1b7a08.png)

修正前のソースはこちら。

```javascript
const SearchSkillHandler = {
  canHandle(handlerInput) {
    console.log('called SearchSkillHandler.canHandle');
    const request = handlerInput.requestEnvelope.request;
    return request.type === 'IntentRequest'
　          && request.intent.name === 'SearchSkillIntent';
  },
  handle(handlerInput) {
    const skillsNameValue = getSlotValue(handlerInput.requestEnvelope, 'skills');
    console.log('called SearchSkillHandler.handle');

    const params = {
        TableName: 'skillmap',
        KeyConditionExpression: 'skill = :skill',
        ExpressionAttributeValues: {
            ':skill': `${skillsNameValue}`
        }
    };

    let skillsPersonName = '';
    documentClient.query(params, (err, data) => {
        if (err) {
            console.log(JSON.stringify(err, null, 2));
        } else {
            console.log(JSON.stringify(data, null, 2));
            console.log('取得したもの name : ' + data.Items[0].name);
            console.log('取得したもの skill : ' + data.Items[0].skill);
            skillsPersonName = data.Items[0].name;
            console.log('取得したもの skillsPersonName1 : ' + skillsPersonName);
        }
    });

    console.log('取得したもの skillsPersonName2 : ' + skillsPersonName);

    return handlerInput.responseBuilder
            .speak(`${skillsNameValue}` + "は" + `${skillsPersonName}` + "さんが詳しいです。")
            .getResponse();
  }
};
```

### ログを追ってみた
困ったときはログ。ということで、CloudWatchのログを見てみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/726018/817e6e56-0274-55b1-d07a-f4aa829e167f.png)

よく見てみると、**skillsPersonName2のほうがskillsPersonName1より早くログにでている。**たぶん、DynamoDBからのデータ取得処理は非同期処理なんだろう。


### 非同期処理という仮説に基づき対応
修正後のソースはこちら。

```javascript
const SearchSkillHandler = {
  canHandle(handlerInput) {
    console.log('called SearchSkillHandler.canHandle');
    const request = handlerInput.requestEnvelope.request;
    return request.type === 'IntentRequest'
　          && request.intent.name === 'SearchSkillIntent';
  },
  async handle(handlerInput) {
    const skillsNameValue = getSlotValue(handlerInput.requestEnvelope, 'skills');
    console.log('called SearchSkillHandler.handle');

    const params = {
        TableName: 'skillmap',
        KeyConditionExpression: 'skill = :skill',
        ExpressionAttributeValues: {
            ':skill': `${skillsNameValue}`
        }
    };

    let skillsPersonName = '';
    await documentClient.query(params, (err, data) => {
        if (err) {
            console.log(JSON.stringify(err, null, 2));
        } else {
            console.log(JSON.stringify(data, null, 2));
            console.log('取得したもの name : ' + data.Items[0].name);
            console.log('取得したもの skill : ' + data.Items[0].skill);
            skillsPersonName = data.Items[0].name;
            console.log('取得したもの skillsPersonName1 : ' + skillsPersonName);
        }
    }).promise();

    console.log('取得したもの skillsPersonName2 : ' + skillsPersonName);

    return handlerInput.responseBuilder
            .speak(`${skillsNameValue}` + "は" + `${skillsPersonName}` + "さんが詳しいです。")
            .getResponse();
  }
};
```

handleの関数にasyncをつけたのと、documentClient.queryにawaitとpromiseをつけて同期処理にしました。

### うまくいった！！
ちゃんと返してくれました！ログをみて仮説を立てて、対応という基本の動きにそって動けた！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/726018/36364f0d-32f3-f388-add3-3ca41de41f77.png)