Edited at

よく見るけどよくわからないasync/await


はじめに


非同期処理とは?

非同期処理ってどういうこと?JavaScriptで一から学ぶ https://qiita.com/kiyodori/items/da434d169755cbb20447


Callback関数とCallback地獄


  • Callback関数:非同期な処理が完了したら実行する関数

  • いろいろなところで使用される


    • イベントリスナ(クリックされたら〇〇を実行)

    • ファイル読み込み(ファイルを読み込んだら〇〇を実行)

    • Ajax通信(通信が終わったら〇〇を実行)

    • などなど



  • 問題点:シンプルな処理であれば問題ないが、Callbackのネストが始まると途端に辛くなる


課題1:Callbackのネストを体感する(15~25分)


  • 目的:連続した非同期処理を行いたい状況でCallbackを使用すると、Callbackがネストし可読性が低くなることを体感する。

  • 内容:以下の1~3を実現する。



    1. DynamoDBからユーザーレコードを取得する。


    これをLambdaに貼り付けてください

    const AWS = require('aws-sdk');
    
    const documentClient = new AWS.DynamoDB.DocumentClient({region: 'ap-northeast-2'});

    exports.handler = (event) => {
    console.log("[START]");
    const param1 = {
    TableName: 'async-lecture-users',
    Key: {
    userId: 'U0001',
    },
    };
    documentClient.get(param1, (err, data) => {
    if (err) {
    console.error(err);
    return;
    }
    console.log(data);
    });
    console.log("[END]");
    };






    1. レコード取得処理を追加する。


    • 内容:ユーザーレコードのグループIDをもとに、グループレコードを取得する。

    • ポイント:1.で取得したグループIDもとに、グループレコードを取得する→documentClient.getがネストするはず!

    • 条件:

    {
    
    TableName: 'async-lecture-groups',
    Key: {
    groupId: data.Item.groupId, // 1.で取得したユーザーレコードのグループID
    },
    }




    1. さらにレコード取得処理を追加する。


    • 内容:グループレコードの平社員IDをもとに、ユーザーレコードを取得する。

    • 条件:

    {
    
    TableName: 'async-lecture-users',
    Key: {
    userId: data.Item.hiraShainId, // 2.で取得したグループレコードの平社員ID
    },
    }



解答例

    const AWS = require('aws-sdk');

const documentClient = new AWS.DynamoDB.DocumentClient({
region: 'ap-northeast-2',
});

exports.handler = (event) => {
console.log('[START]');
const param1 = {
TableName: 'async-lecture-users',
Key: {
userId: 'U0001',
},
};
documentClient.get(param1, (err, data) => {
if (err) {
console.error(err);
return;
}
console.log(data);

const param2 = {
TableName: 'async-lecture-groups',
Key: {
groupId: data.Item.groupId, // 1.で取得したユーザーレコードのグループID
},
};
documentClient.get(param2, (err, data) => {
if (err) {
console.error(err);
return;
}
console.log(data);

const param3 = {
TableName: 'async-lecture-users',
Key: {
userId: data.Item.hiraShainId, // 2.で取得したグループレコードの平社員ID
},
};
documentClient.get(param3, (err, data) => {
if (err) {
console.error(err);
return;
}
console.log(data);
});
});
});
console.log('[END]');
};


Promiseの登場

Promise再入門① ~Promise基本編~ https://qiita.com/tfrcm/items/1dfe4265c36bea903ab3

Promiseについて0から勉強してみた https://qiita.com/toshihirock/items/e49b66f8685a8510bd76


課題2:CallbackのネストをPromiseで解消する(10~20分)


  • 目的:Promiseを使うと、Callbackのネストを解消できることを確認する。

  • 内容:課題1.1~1.3の内容をPromiseを使って記述する。


解答例

    const AWS = require('aws-sdk');

const documentClient = new AWS.DynamoDB.DocumentClient({
region: 'ap-northeast-2',
});

exports.handler = (event) => {
console.log('[START]');
const param1 = {
TableName: 'async-lecture-users',
Key: {
userId: 'U0001',
},
};

documentClient.get(param1).promise()
.then((data) => {
console.log(data);

const param = {
TableName: 'async-lecture-groups',
Key: {
groupId: data.Item.groupId,
},
};

// thenブロックでPromiseをリターンすることで、次のthenの引数にデータを渡せる
return documentClient.get(param).promise();
})
.then((data) => {
console.log(data);

const param = {
TableName: 'async-lecture-users',
Key: {
userId: data.Item.hiraShainId,
},
};

return documentClient.get(param).promise();
})
.then((data) => {
console.log(data);
})
.catch((err) => {
console.error(err);
});
console.log('[END]');
};


async/awaitの時代

async await の使い方 https://qiita.com/niusounds/items/37c1f9b021b62194e077


課題3:async/awaitで書く(10~20分)


  • 目的:async/awaitを使うと簡潔に非同期処理を記述できることを確認する。

  • 内容:課題1.1~1.3の内容をasync/awaitを使って記述する。


解答例

    const AWS = require('aws-sdk');

const documentClient = new AWS.DynamoDB.DocumentClient();

exports.handler = (event) => {
console.log('[START]');
const param1 = {
TableName: 'async-lecture-users',
Key: {
userId: 'U0001',
},
};

documentClient.get(param1).promise()
.then((data) => {
console.log(data);

const param = {
TableName: 'async-lecture-groups',
Key: {
groupId: data.Item.groupId,
},
};

// thenブロックでPromiseをリターンすることで、次のthenの引数にデータを渡せる
return documentClient.get(param).promise();
})
.then((data) => {
console.log(data);

const param = {
TableName: 'async-lecture-users',
Key: {
userId: data.Item.hiraShainId,
},
};

return documentClient.get(param).promise();
})
.then((data) => {
console.log(data);
console.log('[END]');
})
.catch((err) => {
console.error(err);
});
};