【NodeJS】AWS Lambda＋APIGateway＋DynamoDBでTODOアプリを作成

## はじめに
サーバーレスを趣味で始めてみたので、勉強がてらAWS Lambda＋APIGateway＋DynamoDBでTODOアプリを作成し始めました。
個人のメモとして、サーバー側とクライアント側での処理を記事にまとめます。（まだ作成途中です）

## 概要
Lambdaで使用する言語はNode
DynamoDBはidとtodoという項目のみを持ちます。
テーブル名は「todoTable」
今回は、GETとPOSTのみを実装します。

## Lambdaで関数作成
本来であれば１つの関数にまとめたかったのですが、GETメソッドであることをLambdaに渡す方法がわからず、ひとまず関数を分けました。

まずはGETメソッドから。
単純に全てのカラムを取得します。（本来はあまりscanは使わない方がいいらしいが）

```js
const AWS = require('aws-sdk')
const dynamo = new AWS.DynamoDB.DocumentClient()

exports.handler = (event, context, callback) => {
    const httpMethod = event.httpMethod
    const params = {
        'TableName': 'todoTable'
    }
    dynamo.scan(params, function (err, data) {
        const response = {
            statusCode: 200,
            body: JSON.stringify(data.Items)
        }
        callback(null, response)
    })
};
```

クライアント側でbodyからtodoListを取り出し表示するようにします。

続いてPOSTメソッド。

```js
const AWS = require('aws-sdk')
const dynamo = new AWS.DynamoDB.DocumentClient()

exports.handler = (event, context, callback) => {
    const params = {
        'TableName': 'todoTable',
        'Item': {
            'id': event.id,
            'todo': event.todo
        }
    }
    dynamo.put(params, function(err, data) {
        if (err) {
            console.log('error')
        } else {
            console.log('success')
            const response = {
                statusCode: 200,
                body: JSON.stringify(data)
            }
            context.done(null, response)
        }
    })
};

```

try-catchでやるべきですが、今回は簡略化のためこのような実装にしました。（あとで全てtyr-catchに直します）
なぜかここでcallbackを使うと怒られました。
理由分かる方、教えていただきたいです。

あとはAPIGatewayでこれらの関数を各メソッドに割り当てて、デプロイしてください。
詳細は省きます。

## クライアントサイド
今回はjQueryは使わずにXMLHttpRequestを使用して実装します。

まずは、画面がロードされた際にGETメソッドでテーブルの項目を取得し、表示をします。

```js
window.onload = () => {
    const request = new XMLHttpRequest()

    request.open('GET', 'https://ほにゃらら.amazonaws.com/dev', true)
    request.responseType = 'json'

    request.onload = event => {
        const data = this.response
        const todoList = JSON.parse(data.body)
        for (task of todoList) {
            const item = task.todo
            // HTMLのulにliを突っ込むだけのメソッド
            createTodoList(item)
        }
    }

    request.send()
}
```

特に難しい部分はなし。

続いて、TODOを追加した際に走るイベントを追加。

```js
// addというinputタグにイベントを追加
const addTask = document.querySelector('.add')
addTask.addEventListener('submit', e => {
    e.preventDefault()

    const id = Math.random().toString(36).slice(-8);
    const task = addTask.add.value.trim()
    const item = {
        'id': id,
        'todo': task
    }

    const request = new XMLHttpRequest()
    request.open('POST', 'https://ほにゃらら.amazonaws.com/dev/insert', true)
    request.setRequestHeader('Content-Type', 'application/json' );

    request.send(JSON.stringify(item))

    if (task.length){
        createTodoList(task)
        addTask.reset()
    }
})
```

これで完成です。サーバーレスは短時間で割といろいろできて楽しいですね！

## 躓いたところ
### CORS問題
```
Access-Control-Allow-Origin 
```
これを理由にずっと怒られていました。
↓参考記事
[【解説付き】chromeでXMLHttpRequestをローカルのファイルで行う方法](https://qiita.com/growsic/items/a919a7e2a665557d9cf4)
[AWS API Gateway クロスドメイン通信](https://qiita.com/tanj/items/e4486f9af5d7a903117d)

### XMLHttpRequestのパラメータの渡し方
現在のコード

```js
request.send(JSON.stringify(item))
```


過去のコード（エラー発生）

```js
request.send(item)
```

JSON形式にしておらず、３０分くらい悩まされていました。。。

## 終わり
今後はUPDATE、DELETEの実装をし、全て１つの関数にまとめたいと思っています。
それが終わったらなんかしらアプリ作ってみようかな。