Javascript cơ bản: ES6 Promise, Async/Await – cách giải quyết các Function lồng nhau phức tạp

Các function lồng nhau nhiều cấp trong Js là vấn đề muôn thuở, bạn thấy khi click button thì callback thực thi function f1, f1 lại gọi API lấy data để callback f2, f2 gọi API khác để lấy data callback f3, f3 gọi API để lưu trũ dữ liệu sau đó callback f4, …..
Cứ như vậy các function lồng vào nhau nhiều cấp từ ngoài vào trong rất phức tạp, người ta gọi là callback hell (callback chrismas tree) của Javascript

Cách viết tinh gọn không lồng nhau trong Javascript khi không dùng callback là sử dụng Promise (ES6) hoặc Async/Await (ES7).

So sánh cách viết bằng Callback, Promise và Aync/Await
// Lấy thông tin chi tiết của pokemon đầu tiên trong 12 con trả về.

// jQuery là thư viện sử dụng callback
function getDataCallback() {
  $.get("https://pokeapi.co/api/v2/pokemon?limit=12", function(pokemon) {
    $.get(
      `https://pokeapi.co/api/v2/pokemon/${pokemon.results[0].name}`,
      function(data) {
        console.log(data);
      }
    );
  });
}

// fetch trả về một Promise sau từ khóa 'then',
// 'then' sau nhận đầu vào là kết quả trả về từ 'then' trước đó
function getDataPromise() {
  fetch("https://pokeapi.co/api/v2/pokemon?limit=12")
    .then(promise => promise.json())
    .then(pokemon =>
      fetch(`https://pokeapi.co/api/v2/pokemon/${pokemon.results[0].name}`)
    )
    .then(promise2 => promise2.json())
    .then(data => console.log(data));
}

// await phải nằm trong hàm async
async function getDataAsync() {
  let promise = await fetch("https://pokeapi.co/api/v2/pokemon?limit=12");
  let pokemon = await promise.json();
  let promise2 = await fetch(
    `https://pokeapi.co/api/v2/pokemon/${pokemon.results[0].name}`
  );
  let data = await promise2.json();
  console.log(data);
}

getDataPromise();
getDataCallback();
getDataAsync();

Một số tài liệu về Promise và Async/Await