LoginSignup
1
0

More than 3 years have passed since last update.

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

Posted at

Alexaが人を返してくれない

DynamoDBからあるスキルに詳しい人の名前を取得してAlexaに返してもらおうとしている。DynamoDBへアクセスはできているが、なぜか人の名前を返してくれず、「さん」しか出てこない。
image.png

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

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

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

非同期処理という仮説に基づき対応

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

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

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0