Hướng dẫn làm ví dụ Api Gateway và Dynamodb trong AWS Service

1st Feb 2021
Table of contents

Ngày 1.2.2021, Tommy viết ví dụ nhỏ chia sẻ 1 hàm Lambda - runtime Node JS có chức năng insert data vào DynamoDB

Lưu ý. Quá trình thực hiện nếu các bạn gặp lỗi về Redirect has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header'

Bạn xem video sau nhé

>> Hướng dẫn Connect AWS API Gateway đến AWS Lambda (Video)

// Loads in the AWS SDK
const AWS = require('aws-sdk');

// Creates the document client specifing the region 
// The tutorial's table is 'in us-east-1'
const ddb = new AWS.DynamoDB.DocumentClient({region: 'us-east-1'});

exports.handler = async (event, context, callback) => {
    // Captures the requestId from the context message
    const requestId = context.awsRequestId;
    if(event.name && event.email && event.message) {
        // Handle promise fulfilled/rejected states
        await createMessage(requestId, event).then(() => {
            callback(null, {
                statusCode: 201,
                body: '',
                headers: {
                    'Access-Control-Allow-Origin' : '*'
                }
            });
        }).catch((err) => {
            console.error(err)
        })
    } else {
        callback(null, {
            statusCode: 400,
            body: 'Bad Request',
            headers: {
                'Access-Control-Allow-Origin' : '*'
            }
        });
    }
};

// Function createMessage
// Writes message to DynamoDb table Message 
function createMessage(requestId, event) {
    
    const params = {
        TableName: 'Message',
        Item: {
            'messageId' : requestId,
            'name' : event.name,
            'email' : event.email,
            'message' : event.message
        }
    }

    return ddb.put(params).promise();
}

Source HTML dưới đây

<html>
    <script>
        async function getMessages() {
            fetch( 'YOUR API URL HERE',  {
                method: 'GET'
              })
            .then(response => response.json())
            .then((response) => {
                console.log(response.body);
                response.body.forEach(element => {
                    document.getElementById("messages").innerHTML += "<p>"+element.message+"</p>"; // Adds each message to div
                });
            });
        }
        async function submitMessage() {
            var name = document.getElementById("name").value;
            var email = document.getElementById("email").value;
            var message = document.getElementById("message").value;
            fetch( 'YOUR API URL HERE',  {
                method: 'POST',
                body: JSON.stringify({
                    "name": name,
                    "email": email,
                    "message": message
                })
            })
            .then(response => response.json())
            .then((response) => {
                console.log(response);
                document.getElementById("messages").innerHTML += "<p>"+message+"</p>"; // Add new message to message list
            });
        }
        getMessages(); // Calls get message on load
    </script>   
    <head>  
        <title>Test Form</title>
    </head>
    <body>
        <form onsubmit="submitMessage();return false;">
            <label for="name">Name:</label><br>
            <input type="text" id="name" name="name" value=""/><br>
            <label for="email">Email:</label><br>
            <input type="text" id="email" name="email" value=""/><br>
            <label for="message">Message:</label><br>
            <textarea id="message" name="message" value="" rows="10" cols="30"></textarea><br><br>
            <input type="submit" value="Submit">
      </form> 
      <strong>Messages from DynamoDB</strong>
      <div id="messages">

      </div>
    </body>
</html>

Kết quả

Kết quả

Giải thích thuật ngữ

Async / Await là gì?

  • Async / Await là một tính năng của JavaScript giúp chúng ta làm việc với các hàm bất đồng bộ theo cách thú vị hơn và dễ hiểu hơn. Nó được xây dựng trên Promises và tương thích với tất cả các Promise dựa trên API. Trong đó:

  • Async - khai báo một hàm bất đồng bộ (async function someName(){...}).

    • Tự động biến đổi một hàm thông thường thành một Promise.
    • Khi gọi tới hàm async nó sẽ xử lý mọi thứ và được trả về kết quả trong hàm của nó.
    • Async cho phép sử dụng Await.
  • Await - tạm dừng việc thực hiện các hàm async. (Var result = await someAsyncCall ().

    • Khi được đặt trước một Promise, nó sẽ đợi cho đến khi Promise kết thúc và trả về kết quả.
    • Await chỉ làm việc với Promises, nó không hoạt động với callbacks.
    • Await chỉ có thể được sử dụng bên trong các function async.

Dưới đây là một ví dụ đơn giản mà hy vọng sẽ rõ ràng những điều trên:

  • Giả sử chúng ta muốn lấy một số tệp JSON từ máy chủ của mình. Chúng ta sẽ viết một hàm sử dụng thư viện axios và gửi yêu cầu HTTP GET đến Https://tutorialzine.com/misc/files/example.json . Chúng ta phải chờ đợi phản hồi từ máy chủ, đây là một yêu cầu HTTP không đồng bộ.

  • Dưới đây chúng ta sẽ viết cùng một chức năng với 2 cách khác nhau: cách thứ 1 với Promises, và cách thứ 2 với Async / Await

Vậy khi có Async / Await có làm cho promises lỗi thời?

  • Không hoàn toàn. Khi làm việc với Async / Await, thật ra chúng ta vẫn đang sử dụng ngầm Promises. Vì thế, kể cả khi đang sử dụng Async / Await cần một sự hiểu biết tốt về Promises sẽ rất tốt cho chúng ta.

  • Ngoài ra, có những trường hợp mà Async / Await không sử dụng được và chúng ta phải sử dụng Promises. Ví dụ như khi chúng ta cần gọi nhiều thao tác bất đồng bộ và chờ cho tất cả chúng kết thúc. Nếu chúng ta thử và làm điều này với async và await, Điều gì sẽ xảy ra: Hãy xem ví dụ dưới đây các bạn sẽ thấy

     async  function  getABC () {
      let A = await getValueA(); // getValueA takes 2 second to finish
      let B = await getValueB(); // getValueB takes 4 second to finish
      let C = await getValueC(); // getValueC takes 3 second to finish

      return A*B*C;
    }
  • Mỗi lần gọi tới hàm await sẽ đợi cho đến khi hàm await trước đó kết thúc. Vì các wait sẽ đợi và thực hiện tuần tự từng cái một, toàn bộ chức năng sẽ mất 9 giây để thực hiện xong hàm từ đầu đến cuối (2 + 4 + 3).
  • Đây không phải là một giải pháp tối ưu vì A, B và C không phụ thuộc vào nhau, chúng ta không cần biết giá trị của A trước khi chúng ta có được B. Vì vậy, chúng ta có thể lấy chúng cùng một lúc và thời gian chờ đợi sẽ được giảm bớt đi.
  • Trong trường hợp như thế này, sử dụng Promise sẽ thích hợp hơn. Để gửi tất cả các yêu cầu cùng lúc, chúng ta sử dụng Promise.all(). Việc sử dụng Promise.all() sẽ đảm bảo chúng ta có tất cả các kết quả trước khi tiếp tục thực thi code, nhưng việc gọi đến các hàm bất đồng bộ sẽ được chạy song song mà không phải tuần tự từng cái một.
    async  function  getABC () {
      // Promise.all() allows us to send all requests at the same time. 
      let results = await Promise.all([ getValueA, getValueB, getValueC ]); 

      return results.reduce((total,value) => total * value);
    }
  • Bằng cách này, thời gian thực thi hàm sẽ mất it hơn. hàm getValueA và getValueC sẽ thực hiện xong trước khi getValueB xong. Thay vì phải mất 9 giây để chờ từng hàm trả về giá trị như trên, chúng ta sẽ chỉ mất 4 giây để chờ cả 3 hàm trả về giá trị.

Xử lý lỗi trong Async / Await

  • Một điều tuyệt vời khác về Async / Await là nó cho phép chúng ta bắt các lỗi không mong đợi bằng cách sử dụng try / catch. Chúng ta chỉ cần để các await call của chúng ta vào trong khối try/catch như sau:
    async function doSomethingAsync(){
        try {
            // This async call may fail.
            let result = await someAsyncCall();
        }
        catch(error) {
            // If it does we will catch the error here.
        }  
    }
  • Mệnh đề catch sẽ xử lý các lỗi gây ra bởi các hàm bất đồng bộ hoặc bất kỳ lỗi nào chúng ta có thể đã viết bên trong khối try.

  • Trong một vài tình huống, chúng ta cũng có thể bắt các lỗi khi đang thực hiện function async. Vì tất cả các hàm async đều trả về Promises, chúng ta chỉ cần gọi thêm hàm .catch() khi gọi chúng.

    // Async function without a try/catch block.
    async function doSomethingAsync(){
        // This async call may fail.
        let result = await someAsyncCall();
        return result;  
    }

    // We catch the error upon calling the function.
    doSomethingAsync().
        .then(successHandler)
        .catch(errorHandler);
  • Dựa vào các tình huống cụ thể, chúng ta sẽ sử dụng try/catch hoặc .catch() để bắt và xử lý lỗi. Tuy nhiên, chúng ta không nên sử dụng cả 2 cùng một lúc vì nó có thể dẫn đến các vấn đề không mong muốn.

Hỗ trợ trình duyệt

  • Async / Await có thể sử dụng trong hầu hết các trình duyệt chính, ngoại trừ IE11 - tất cả các trình duyệt sẽ nhận ra mã async / await của bạn mà không cần các thư viện bên ngoài.
  • Nếu các bạn dùng Node cũng có sử dụng async từ Node 8 trở lên. Nó sẽ trở thành LTS vào cuối năm nay.
  • Nếu cái này không đáp ứng được nhu cầu của bạn, cũng có một số trình chuyển đổi JS như Babel và TypeScript và thư viện Node.js async/await cung cấp các phiên bản nền tảng riêng của tính năng này.
Bạn thấy bài viết này như thế nào?
0 reactions

Add new comment

Image CAPTCHA
Enter the characters shown in the image.
Câu nói tâm đắc: “Điều tuyệt với nhất trong cuộc sống là làm được những việc mà người khác tin là không thể!”

Related Articles

Hiện nay, việc quản lý các web applications khá là phức tạp, ví dụ bạn phải quản lý load balancer, vài web servers, database servers

In this video we'll be setting up a new React App with AWS Amplify to add Sign up, Login and Logout in the easiest way possible.

In this hands on workshop Amazon Developer Advocate Nader Dabit shows us how to get started with serverless GraphQL using AWS Amplify.