+5

Vén màn cơ chế Promise trong Javascript

Xin chào các bạn,bài viết này mình sẽ tổng quan về Promise,cách gọi hàm bất đồng bộ theo kiểu đồng bộ(async...await) và ví dụ về Promise trong React. Trong ví dụ này,mình sẽ hiển thị lên view các quốc gia trên thế giới bao gồm: Quốc kì, diện tích lãnh thổ, dân số... bằng cách call Api. Cùng nhau học Promise thôi nào!

1. Promise

Promise là gì ?

Promise là một cơ chế trong Javascript giúp bạn thực hiện các tác vụ bất đồng bộ.Promise sẽ dừng chương trình lại cho đến khi tác vụ bất đồng bộ được thực hiện xong

3 trạng thái của Promise:

+Pending(Đang thực hiện)

+Resolve(Thực hiện thành công)

+Reject(Thực hiện không thành công)

Cách dùng Promise

Khai báo Promise

const tenBien = new Promise((resolve,reject)=>{

//Thực hiện Promise

})

Promise truyền vào 1 callback function.Trong callback function gồm 2 tham số là resolve và reject, 2 tham số này đều là function.

Gọi Promise

   <tenPromise>
  .then((response)=>{})
  .catch((error)=>{})

Then nhận về dữ liệu trả về thành công,ngược lại catch sẽ nhận dữ liệu không thành công

Dưới đây là ví dụ về 1 Promise hoàn chỉnh với các phép tính cộng,nhân,chia 2 số có then và catch :

    const add = (a, b) => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (typeof a === "number" && typeof b === "number") {
          resolve(a + b);
        } else {
          reject("tham so ham add khong hop le");
        }
      }, 2000);
    });
  };

  const multiple = (a, b) => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (typeof a === "number" && typeof b === "number") {
          resolve(a * b);
        } else {
          reject("tham so ham multiple khong hop le");
        }
      }, 3000);
    });
  };

  const div = (a, b) => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (typeof a === "number" && typeof b === "number") {
          resolve(a / b);
        } else {
          reject("tham so ham div khong hop le");
        }
      }, 3000);
    });
  };
  // gọi Promise
  const addPromise = add(1, 2);
  addPromise
    .then((response) => {
      console.log("response", response);
      const sum = response;
      const multiplePromise = multiple(sum, 2);
      multiplePromise
        .then((res1) => {
          console.log("multiple", res1);
          const mul = res1;
          const divPromise = div(mul, 3);
          divPromise
            .then((res2) => {
              console.log("div", res2);
            })
            .catch((errr) => {
              console.log("div", errr);
            });
        })
        .catch((err) => {
          console.log("multiple", err);
        });
    })
    .catch((err) => {
      console.log("err===", err);
    });

Ở ví dụ trên có thể thấy các hàm callback lồng nhau quá nhiều và nếu mình tiếp tục viết thêm các callback thì code sẽ bị hình tháp.Hay còn gọi là callback hell.

Để khắc phục vấn đề trên,chúng ta sẽ đến với khái niệm tiếp theo : Async...await

2. Async/await

Mục đích chính của async function là thực hiện các tác vụ bất đồng bộ mà không phải đợi cho đến khi tác vụ trước hoàn thành. Thay vì chờ đợi một tác vụ kết thúc, chương trình có thể tiếp tục thực thi các tác vụ khác trong khi tác vụ bất đồng bộ đang thực hiện. Khi tác vụ bất đồng bộ hoàn thành, chương trình có thể trở lại và xử lý kết quả của tác vụ đó.

Cách dùng async/await

Để sử dụng, bạn phải khai báo hàm với từ khóa async. Khi đó bên trong hàm bạn có thể dùng await.

    Const tenFunction = async()=>{
    await Promise
    //await:Dừng chương trình lại đến khi promise thực hiện xong
    //trả về kết quả của promise
    }

***Lưu ý: Hàm async có thể có hoặc không có await nhưng await phải được gọi bên trong hàm async *

Chúng ta sẽ cùng nhau làm lại ví dụ bên trên sử dụng async/await nhé:

    const add = (a, b) => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          if (typeof a === "number" && typeof b === "number") {
            resolve(a + b);
          } else {
            reject("tham so ham add khong hop le");
          }
        }, 3000);
      });
    };

    const multiple = (a, b) => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          if (typeof a === "number" && typeof b === "number") {
            resolve(a * b);
          } else {
            reject("tham so ham multiple khong hop le");
          }
        }, 2000);
      });
    };

    const div = (a, b) => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          if (typeof a === "number" && typeof b === "number") {
            resolve(a / b);
          } else {
            reject("tham so ham div khong hop le");
          }
        }, 1000);
      });
    };

    const calculator = async () => {
      try {
        const sum = await add(1, 2);
        console.log("sum", sum);

        const multipleRes = await multiple(sum, 2);
        console.log("mul", multipleRes);
        const divRes = await div(multipleRes, 3);
        console.log("chu vi =====", divRes);
      } catch (err) {
        console.log("err ====", err);
      }
    };

    calculator();

Sau khi thay đổi thời gian của các hàm thì đoạn code vẫn chạy đồng bộ

Ví dụ Promise trong ReactJs

Nội dung file app.js:

    import "./styles.css";
    import React, { useState, useEffect } from "react";
    export default function App() {
      const [listCountry, setListCountry] = useState([]);
      const [isLoading, setIsLoading] = useState(false);
      useEffect(() => {
        const initData = async () => {
          try {
            const response = await fetch("https://restcountries.com/v3.1/all");
            const result = await response.json();
            setListCountry(result);
            setIsLoading(true);
          } catch (err) {}
        };
        initData();
      }, []);
      if (!isLoading) {
        return (
          <div>
            <h1>Loading...</h1>
          </div>
        );
      }
      if (!listCountry.length) {
        return <div>Empty</div>;
      }
      return (
        <div className="App">
          <div className="wrapper">
            {listCountry.map((item) => {
              return (
                <div className="country">
                  <img src={item.flags.png} width="200px" height="150px" alt="" />
                  <h3>Name:{item.name.common}</h3>
                  <h4>Population:{item.population}</h4>
                  <h4>Area:{item.area}</h4>
                </div>
              );
            })}
          </div>
        </div>
      );
    }

Nội dung file style.css:

    .App {
      font-family: sans-serif;
      text-align: center;
    }
    .wrapper {
      border: 1px solid;
      padding: 8px;
      display: grid;
      grid-template-columns: repeat(5, 1fr);
      gap: 20px;
    }
    .country {
      border: 1px solid;

      padding: 20px;
      background: #f5f4f2;
    }

All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí