0

Những concepts hữu ích của JavaScript nên biết trước khi học React

Để học React - hay bất kỳ framework JavaScript nào - thì trước tiên bạn cần phải hiểu các phương thức và khái niệm JavaScript cơ bản. Việc này giống như việc bạn phải biết đi trước khi chạy vậy. Hãy kiên nhẫn đọc hết bài viết này, vì biết đâu nó có thể giúp ích cho các bạn.

Hàm Callback trong JavaScript

Hàm callback là một hàm được thực thi sau khi một hàm khác đã hoàn thành việc thực thi của nó. Nó thường được cung cấp như một input cho một hàm khác.

Callbacks rất quan trọng cần hiểu vì chúng được sử dụng trong các phương thức mảng (chẳng hạn như map (), filter (), v.v.), setTimeout (), trình lắng nghe sự kiện (chẳng hạn như nhấp, cuộn, v.v.) và nhiều nơi khác.

Dưới đây là ví dụ về trình lắng nghe sự kiện "nhấp chuột" với hàm callback sẽ được chạy bất cứ khi nào nút được nhấp:

//HTML
<button class="btn">Click Me</button>

//JavaScript
const btn = document.querySelector('.btn');

btn.addEventListener('click', () => {
  let name = 'John doe';
  console.log(name.toUpperCase())
})

Lưu ý: Hàm callback có thể là hàm thông thường hoặc hàm mũi tên.

Promises trong JavaScript

Như đã nêu trước đó, một hàm callback được thực thi sau khi hàm gốc được thực thi. Giờ đây, bạn có thể bắt đầu xem xét việc xếp chồng rất nhiều hàm callback lên nhau vì bạn không muốn một hàm cụ thể nào chạy cho đến khi hàm cha đã chạy xong hoặc một khoảng thời gian cụ thể đã trôi qua.

Ví dụ: hãy thử hiển thị 5 tên trong bảng điều khiển sau mỗi 2 giây – nghĩa là, tên đầu tiên xuất hiện sau 2 giây, tên thứ hai sau 4 giây, v.v.

setTimeout(() => {
    console.log("Joel");
    setTimeout(() => {
        console.log("Victoria");
        setTimeout(() => {
            console.log("John");
            setTimeout(() => {
                console.log("Doe");
                setTimeout(() => {
                    console.log("Sarah");
                }, 2000);
            }, 2000);
        }, 2000);
    }, 2000);
}, 2000);

Ví dụ trên sẽ hoạt động, nhưng sẽ khó hiểu, gỡ lỗi hoặc thậm chí thêm xử lý lỗi vào. Điều này được gọi là "Callback Hell". Callback hell là một vấn đề lớn do việc viết code với các callback lồng nhau vô cùng phức tạp.

Lý do chính để sử dụng promises là để ngăn chặn callback hell. Với Promises, chúng ta có thể viết các đoạn mã code không đồng bộ theo cách đồng bộ.

Promise là một đối tượng trả về một giá trị mà bạn mong đợi sẽ thấy trong tương lai nhưng hiện tại không thấy.

Một ứng dụng thực tế cho promises là trong các HTTP request, trong đó bạn gửi một yêu cầu và không nhận được phản hồi ngay lập tức vì đó là một hoạt động không đồng bộ. Bạn chỉ nhận được câu trả lời (dữ liệu hoặc lỗi) khi máy chủ phản hồi.

Cú pháp promise của JavaScript:

const myPromise = new Promise((resolve, reject) => {  
    // condition
});

Promises có hai tham số, một cho thành công (resolve) và một cho thất bại (reject). Mỗi cái có một điều kiện phải được thỏa mãn để Promise được giải quyết - nếu không, nó sẽ bị từ chối:

const promise = new Promise((resolve, reject) => {  
    let condition;

    if(condition is met) {    
        resolve('Promise is resolved successfully.');  
    } else {    
        reject('Promise is rejected');  
    }
});

Có 3 trạng thái của đối tượng Promise:

  • Pending: theo mặc định, đây là Trạng thái ban đầu, trước khi Promise thành công hoặc thất bại.
  • Resolved: Promise đã hoàn thành
  • Rejected: Promise thất bại

Cuối cùng, hãy thử triển khai lại callback hell như một promise:

function addName (time, name){
  return new Promise ((resolve, reject) => {
    if(name){
      setTimeout(()=>{
        console.log(name)
        resolve();
      },time)
    }else{
      reject('No such name');
    }
  })
}

addName(2000, 'Joel')
  .then(()=>addName(2000, 'Victoria'))
  .then(()=>addName(2000, 'John'))
  .then(()=>addName(2000, 'Doe'))
  .then(()=>addName(2000, 'Sarah'))
  .catch((err)=>console.log(err))

Hàm Map() trong JavaScript

Một trong những phương thức được sử dụng thường xuyên nhất là Array.map (), cho phép bạn lặp lại một mảng và sửa đổi các phần tử của nó bằng cách sử dụng hàm callback. Hàm callback sẽ được chạy trên mỗi phần tử mảng.

Giả sử chúng ta có một mảng người dùng chứa thông tin của họ.

let users = [
  { firstName: "Susan", lastName: "Steward", age: 14, hobby: "Singing" },
  { firstName: "Daniel", lastName: "Longbottom", age: 16, hobby: "Football" },
  { firstName: "Jacob", lastName: "Black", age: 15, hobby: "Singing" }
];

Chúng ta có thể lặp lại bằng cách sử dụng map và sửa đổi output của nó

let singleUser = users.map((user)=>{
  //let's add the firstname and lastname together
  let fullName = user.firstName + ' ' + user.lastName;
  return `
    <h3 class='name'>${fullName}</h3>
    <p class="age">${user.age}</p>
  `
});

Bạn cần lưu ý rằng:

  • map () luôn trả về một mảng mới, ngay cả khi đó là một mảng trống.
  • Nó không thay đổi kích thước của mảng ban đầu so với phương thức filter
  • Nó luôn sử dụng các giá trị từ mảng ban đầu của bạn khi tạo một mảng mới.

Lưu ý: Phương thức map hoạt động gần giống như mọi trình vòng lặp JavaScript khác chẳng hạn như forEach () nhưng sẽ thích hợp hơn khi luôn sử dụng phương thức map bất cứ khi nào bạn định trả về một giá trị.

Một trong những lý do chính khiến chúng ta sử dụng map là để chúng ta có thể đóng gói dữ liệu của mình trong một số HTML, trong khi đối với React, điều này chỉ được thực hiện đơn giản bằng cách sử dụng JSX.

Filter () và Find () trong JavaScript

Filter () cung cấp một mảng mới tùy thuộc vào các tiêu chí nhất định. Không giống như map (), nó có thể thay đổi kích thước của mảng mới, trong khi find () chỉ trả về một instance duy nhất (đây có thể là một đối tượng hoặc mục). Nếu tồn tại nhiều kết quả khớp, nó sẽ trả về kết quả khớp đầu tiên - nếu không, nó sẽ trả về undefined.

Giả sử bạn có một bộ sưu tập mảng người dùng đã đăng ký với các độ tuổi khác nhau:

let users = [
  { firstName: "Susan", age: 14 },
  { firstName: "Daniel", age: 16 },
  { firstName: "Bruno", age: 56 },
  { firstName: "Jacob", age: 15 },
  { firstName: "Sam", age: 64 },
  { firstName: "Dave", age: 56 },
  { firstName: "Neils", age: 65 }
];

Bạn có thể chọn sắp xếp dữ liệu này theo nhóm tuổi, chẳng hạn như người trẻ tuổi (từ 1-15 tuổi), người cao tuổi (từ 50-70 tuổi), v.v.

Trong trường hợp này, hàm filter có ích vì nó tạo ra một mảng mới dựa trên tiêu chí. Hãy cùng xem cách thức hoạt động của nó.

// for young people
const youngPeople = users.filter((person) => {
  return person.age <= 15;
});

//for senior people
const seniorPeople = users.filter((person) => person.age >= 50);

console.log(seniorPeople);
console.log(youngPeople);

Điều này tạo ra một mảng mới. Nó tạo ra một mảng trống nếu điều kiện không được thỏa mãn (không khớp).

Find ()

Phương thức find (), giống như phương thức filter (), lặp lại trên mảng để tìm kiếm một instance / mục đáp ứng điều kiện được chỉ định. Khi tìm thấy, nó sẽ trả về mục mảng cụ thể đó và ngay lập tức kết thúc vòng lặp. Nếu không tìm thấy kết quả khớp, hàm sẽ trả về undefined.

Ví dụ:

const Bruno = users.find((person) => person.firstName === "Bruno");
console.log(Bruno);

Destructuring Mảng và Đối tượng trong JavaScript

Destructuring là một tính năng của JavaScript được giới thiệu trong ES6 cho phép truy cập và giải nén các biến từ mảng và đối tượng nhanh hơn và dễ dàng hơn.

Trước khi destructuring được giới thiệu, nếu chúng ta có một mảng các loại trái cây và muốn lấy riêng trái cây thứ nhất, thứ hai và thứ ba, chúng ta sẽ kết thúc với một cái gì đó như thế này:

let fruits= ["Mango", "Pineapple" , "Orange", "Lemon", "Apple"];

let fruit1 = fruits[0];
let fruit2 = fruits[1];
let fruit3 = fruits[2];

console.log(fruit1, fruit2, fruit3); //"Mango" "Pineapple" "Orange"

Điều này giống như lặp đi lặp lại cùng một thứ có thể trở nên cồng kềnh. Hãy xem cách thức này có thể được destructuring để lấy 3 loại trái cây đầu tiên.

let [fruit1, fruit2, fruit3] = fruits;

console.log(fruit1, fruit2, fruit3); //"Mango" "Pineapple" "Orange"

Bạn có thể tự hỏi làm thế nào bạn có thể bỏ qua dữ liệu nếu bạn chỉ muốn in trái cây đầu tiên và cuối cùng hoặc trái cây thứ hai và thứ tư. Bạn sẽ sử dụng dấu phẩy như sau:

const [fruit1 ,,,, fruit5] = fruits;
const [,fruit2 ,, fruit4,] = fruits;

Destructuring đối tượng

Bây giờ, hãy xem cách chúng ta có thể destructuring một đối tượng - bởi vì trong React, bạn sẽ thực hiện rất nhiều destructuring đối tượng.

Giả sử chúng ta có một đối tượng người dùng chứa firstname, lastname và nhiều thứ khác nữa,

const Susan = {
  firstName: "Susan",
  lastName: "Steward",
  age: 14,
  hobbies: {
    hobby1: "singing",
    hobby2: "dancing"
  }
};

Theo cách cũ, việc lấy những dữ liệu này có thể gây căng thẳng và lặp đi lặp lại nhiều lần:

const firstName = Susan.firstName;
const age = Susan.age;
const hobby1 = Susan.hobbies.hobby1;

console.log(firstName, age, hobby1); //"Susan" 14 "singing"

nhưng với destructuring thì dễ dàng hơn rất nhiều:

const {firstName, age, hobbies:{hobby1}} = Susan;

console.log(firstName, age, hobby1); //"Susan" 14 "singing"

Chúng ta cũng có thể làm điều này bên trong một hàm:

function individualData({firstName, age, hobbies:{hobby1}}){
  console.log(firstName, age, hobby1); //"Susan" 14 "singing"
}
individualData(Susan);

Rest và Spread Operators trong JavaScript

Toán tử spread và rest trong JavaScript sử dụng ba dấu chấm .... Toán tử rest thu thập hoặc tập hợp các mục - nó đặt phần còn lại (“rest”) của một số giá trị cụ thể do người dùng cung cấp vào một mảng / đối tượng JavaScript.

Giả sử bạn có một mảng các loại trái cây:

let fruits= ["Mango", "Pineapple" , "Orange", "Lemon", "Apple"];

Chúng ta có thể destructuring để lấy trái cây thứ nhất và thứ hai và sau đó đặt phần còn lại (“rest”) của trái cây vào một mảng bằng cách sử dụng toán tử rest.

const [firstFruit, secondFruit, ...rest] = fruits

console.log(firstFruit, secondFruit, rest); //"Mango" "Pineapple" ["Orange","Lemon","Apple"]

Nhìn vào kết quả, bạn sẽ thấy hai mục đầu tiên và sau đó là mục thứ ba là một mảng bao gồm các loại trái cây còn lại mà chúng ta chưa destructuring. Giờ đây, chúng ta có thể tiến hành bất kỳ loại xử lý nào trên mảng mới được tạo, chẳng hạn như:

const chosenFruit = rest.find((fruit) => fruit === "Apple");

console.log(`This is an ${chosenFruit}`); //"This is an Apple"

Điều quan trọng cần lưu ý là điều này phải luôn đến sau cùng (vị trí rất quan trọng).

Chúng ta vừa làm việc với mảng - bây giờ hãy xử lý các đối tượng, chúng hoàn toàn giống nhau.

Giả sử chúng ta đã có một đối tượng người dùng có firstname, lastname và nhiều thứ khác nữa. Chúng ta có thể destructuring nó và sau đó trích xuất phần còn lại của dữ liệu.

const Susan = {
  firstName: "Susan",
  lastName: "Steward",
  age: 14,
  hobbies: {
    hobby1: "singing",
    hobby2: "dancing"
  }
};

const {age, ...rest} = Susan;
console.log(age, rest);

Điều này sẽ ghi lại kết quả sau:

14
{
firstName: "Susan" ,
lastName: "Steward" ,
hobbies: {...}
}

Toán tử Spread

Toán tử spread, đúng như tên gọi, được sử dụng để trải rộng các mục mảng. Nó cung cấp cho chúng ta khả năng nhận được một danh sách các tham số từ một mảng. Toán tử spread có cú pháp tương tự như toán tử rest, ngoại trừ nó hoạt động theo hướng ngược lại.

Lưu ý: Toán tử spread chỉ có hiệu lực khi được sử dụng trong các mảng literal, lời gọi hàm hoặc các đối tượng thuộc tính được khởi tạo.

Ví dụ, giả sử bạn có các mảng các loại động vật khác nhau:

let pets= ["cat", "dog" , "rabbits"];

let carnivorous = ["lion", "wolf", "leopard", "tiger"];

Bạn có thể muốn kết hợp hai mảng này thành chỉ một mảng động vật. Hãy thử nghiệm nó:

let animals = [pets, carnivorous];

console.log(animals); //[["cat", "dog" , "rabbits"], ["lion", "wolf", "leopard", "tiger"]]

Đây không phải là những gì chúng ta muốn - chúng ta muốn tất cả các mục chỉ trong một mảng duy nhất. Và chúng ta có thể đạt được điều này bằng cách sử dụng toán tử spread:

let animals = [...pets, ...carnivorous];

console.log(animals); //["cat", "dog" , "rabbits", "lion", "wolf", "leopard", "tiger"]

Điều này cũng hoạt động với các đối tượng. Điều quan trọng cần lưu ý là toán tử spread không thể mở rộng các giá trị của đối tượng literal, vì đối tượng thuộc tính không phải là một iterable. Nhưng chúng ta có thể sử dụng nó để sao chép các thuộc tính từ đối tượng này sang đối tượng khác.

Ví dụ:

let name = {firstName:"John", lastName:"Doe"};
let hobbies = { hobby1: "singing", hobby2: "dancing" }
let myInfo = {...name, ...hobbies};

console.log(myInfo); //{firstName:"John", lastName:"Doe", hobby1: "singing", hobby2: "dancing"}

Giá trị duy nhất - Set () trong JavaScript

Gần đây, tôi đã cố gắng tạo một tab danh mục cho một ứng dụng, nơi tôi cần tìm nạp giá trị danh mục từ một mảng.

let animals = [
  {
    name:'Lion',
    category: 'carnivore'
  },
  {
    name:'dog',
    category:'pet'
  },
  {
    name:'cat',
    category:'pet'
  },
  {
    name:'wolf',
    category:'carnivore'
  }
]

Điều đầu tiên là lặp lại mảng, nhưng tôi nhận được các giá trị lặp lại:

let category = animals.map((animal)=>animal.category);
console.log(category); //["carnivore" , "pet" , "pet" , "carnivore"]

Điều này có nghĩa là tôi cần thiết lập một điều kiện để tránh lặp lại. Nó hơi phức tạp một chút cho đến khi tôi bắt gặp hàm tạo / đối tượng set () được cung cấp bởi ES6.

Set là một tập hợp các mục là duy nhất, nghĩa là không có phần tử nào có thể được lặp lại. Hãy xem cách chúng ta có thể thực hiện điều này một cách dễ dàng.

//wrap your iteration in the set method like this
let category = [...new Set(animals.map((animal)=>animal.category))];

console.log(category); ////["carnivore" , "pet"]

Khóa đối tượng động trong JavaScript

Điều này cho phép chúng ta thêm các khóa đối tượng bằng cách sử dụng ký hiệu dấu ngoặc vuông. Điều này có thể không có ý nghĩa gì với bạn ngay bây giờ, nhưng khi bạn tiếp tục học React hoặc bắt đầu làm việc với các nhóm, bạn có thể bắt gặp nó.

Trong JavaScript, chúng ta biết rằng các đối tượng thường được tạo thành từ các thuộc tính / khóa và giá trị và chúng ta có thể sử dụng dấu chấm để thêm, chỉnh sửa hoặc truy cập một số giá trị. Ví dụ:

let lion = {
  category: "carnivore"
};

console.log(lion); // { category: "carnivore" }
lion.baby = 'cub';
console.log(lion.category); // carnivore
console.log(lion); // { category: "carnivore" , baby: "cub" }

Chúng ta cũng có tùy chọn sử dụng ký hiệu dấu ngoặc vuông, được sử dụng khi chúng ta cần khóa đối tượng động.

Chúng ta muốn nói gì khi nói đến khóa đối tượng động? Đây là những khóa có thể không tuân theo quy ước đặt tên tiêu chuẩn của các thuộc tính / khóa trong một đối tượng. Quy ước đặt tên tiêu chuẩn chỉ cho phép camelCase và snake_case, nhưng bằng cách sử dụng ký hiệu dấu ngoặc vuông, chúng ta có thể giải quyết vấn đề này.

Ví dụ: giả sử chúng ta đặt tên cho khóa của mình bằng một dấu gạch ngang giữa các từ, ví dụ (lion-baby):

let lion = {
  'lion-baby' : "cub"
};

// dot notation
console.log(lion.lion-baby); // error: ReferenceError: baby is not defined
// bracket notation
console.log(lion['lion-baby']); // "cub"

Bạn có thể thấy sự khác biệt giữa dấu chấm và ký hiệu dấu ngoặc vuông. Hãy xem các ví dụ khác:

let category = 'carnivore';
let lion = {
  'lion-baby' : "cub",
  [category] : true,
};

console.log(lion); // { lion-baby: "cub" , carnivore: true }

Bạn cũng có thể thực hiện các phép toán phức tạp hơn bằng cách sử dụng các điều kiện trong dấu ngoặc vuông, như thế này:

const number = 5;
const gavebirth = true;

let animal = {
  name: 'lion',
  age: 6,
  [gavebirth && 'babies']: number
};

console.log(animal); // { name: "lion" , age: 6 , babies: 5 }

Reduce () trong JavaScript

Đây được cho là hàm mảng mạnh mẽ nhất. Nó có thể thay thế các phương thức filter () và find () và cũng khá tiện dụng khi thực hiện các phương thức map () và filter () trên một lượng lớn dữ liệu.

Khi bạn xâu chuỗi phương thức map và filter lại với nhau, bạn sẽ kết thúc bằng cách thực hiện công việc hai lần - trước tiên là lọc mọi giá trị duy nhất và sau đó là ánh xạ các giá trị còn lại. Mặt khác, reduce () cho phép bạn lọc và ánh xạ trong một lần duy nhất. Phương pháp này rất mạnh mẽ, nhưng nó cũng phức tạp và khó khăn hơn một chút.

Chúng ta lặp lại mảng của mình và sau đó thu được một hàm callback, tương tự như map (), filter (), find () và những hàm khác. Sự khác biệt chính là nó giảm mảng của chúng ta thành một giá trị duy nhất, có thể là số, mảng hoặc đối tượng.

Một điều cần lưu ý về phương thức reduce () là chúng ta đang chuyển vào hai đối số, điều này chưa từng xảy ra kể từ khi bạn bắt đầu đọc hướng dẫn này.

Đối số đầu tiên là tổng / tổng của tất cả các phép tính và đối số thứ hai là giá trị lặp hiện tại (bạn sẽ hiểu rõ hơn trong giây lát).

Ví dụ, giả sử chúng ta có một danh sách tiền lương cho nhân viên của mình:

let staffs = [
  { name: "Susan", age: 14, salary: 100 },
  { name: "Daniel", age: 16, salary: 120 },
  { name: "Bruno", age: 56, salary: 400 },
  { name: "Jacob", age: 15, salary: 110 },
  { name: "Sam", age: 64, salary: 500 },
  { name: "Dave", age: 56, salary: 380 },
  { name: "Neils", age: 65, salary: 540 }
];

Và tôi muốn tính toán khoản tiền thập phân 10% cho tất cả nhân viên. Chúng ta có thể dễ dàng thực hiện việc này bằng phương thức reduce, nhưng trước khi làm điều đó, hãy làm một việc dễ dàng hơn: trước tiên hãy tính tổng lương.

const totalSalary = staffs.reduce((total, staff) => {
  total += staff.salary;
  return total;
},0)
console.log(totalSalary); // 2150

Lưu ý: Tôi đã chuyển một đối số thứ hai là tổng số, nó có thể là bất cứ thứ gì - ví dụ: một số hoặc một đối tượng.

Bây giờ, hãy tính toán khoản tiền thập phân 10% cho tất cả nhân viên và nhận tổng số. Chúng ta có thể chỉ cần lấy 10% từ tổng số hoặc trước tiên lấy nó từ mỗi mức lương trước khi cộng chúng lại.

const salaryInfo = staffs.reduce(
  (total, staff) => {
    let staffTithe = staff.salary * 0.1;
    total.totalTithe += staffTithe;
    total['totalSalary'] += staff.salary;
    return total;
  },
  { totalSalary: 0, totalTithe: 0 }
);

console.log(salaryInfo); // { totalSalary: 2150 , totalTithe: 215 }

Optional Chaining trong JavaScript

Optional chaining là một cách an toàn để truy cập các thuộc tính đối tượng lồng nhau trong JavaScript thay vì phải thực hiện nhiều kiểm tra null khi truy cập một chuỗi dài các thuộc tính đối tượng. Đây là một tính năng mới được giới thiệu trong ES2020.

Ví dụ:

let users = [
{
    name: "Sam",
    age: 64,
    hobby: "cooking",
    hobbies: {
      hobb1: "cooking",
      hobby2: "sleeping"
    }
  },
  { name: "Bruno", age: 56 },
  { name: "Dave", age: 56, hobby: "Football" },
  {
    name: "Jacob",
    age: 65,
    hobbies: {
      hobb1: "driving",
      hobby2: "sleeping"
    }
  }
];

Giả sử bạn đang cố gắng lấy sở thích từ mảng ở trên. Hãy thử nghiệm nó:

users.forEach((user) => {
  console.log(user.hobbies.hobby2);
});

Khi bạn nhìn vào bảng điều khiển của mình, bạn sẽ nhận thấy rằng lần lặp đầu tiên đã hoàn thành, nhưng lần lặp thứ hai không có sở thích. Vì vậy, nó đã phải đưa ra lỗi và thoát khỏi lần lặp - điều đó có nghĩa là nó không thể lấy dữ liệu từ các Đối tượng khác trong mảng.

Kết quả:

"sleeping"
error: Uncaught TypeError: user.hobbies is undefined

Lỗi này có thể được khắc phục bằng optional chaining, mặc dù có một số phương pháp có thể khắc phục lỗi này (ví dụ: sử dụng điều kiện). Hãy xem cách chúng ta sẽ thực hiện việc này với cả điều kiện và optional chaining:

Phương pháp kết xuất có điều kiện:

users.forEach((user) => {
  console.log(user.hobbies && user.hobbies.hobby2);
});

Optional chaining:

users.forEach((user) => {
  console.log(user ?.hobbies ?.hobby2);
});

Kết quả:

"sleeping"
undefined
undefined
"sleeping"

Lấy API & Lỗi trong JavaScript

API fetch, như tên gọi của nó, được sử dụng để lấy dữ liệu từ API. Đây là API trình duyệt cho phép bạn sử dụng JavaScript để thực hiện các yêu cầu AJAX (JavaScript và XML không đồng bộ) cơ bản.

Vì nó được cung cấp bởi trình duyệt, bạn có thể sử dụng nó mà không cần phải cài đặt hoặc nhập bất kỳ gói hoặc phụ thuộc nào (như axios). Cấu hình của nó khá đơn giản để nắm bắt. API fetch cung cấp một lời hứa theo mặc định (tôi đã đề cập đến lời hứa trước đó trong bài viết này).

Hãy cùng xem cách lấy dữ liệu thông qua API lấy dữ liệu. Chúng ta sẽ sử dụng API miễn phí chứa hàng nghìn trích dẫn ngẫu nhiên:

fetch("https://type.fit/api/quotes")
  .then((response) => response.json())
  .then((data) => console.log(data))
  .catch((err) => console.log(err));

Những gì tôi đã làm ở đây là:

  • Dòng 1: chúng tôi lấy dữ liệu từ API, trả về một lời hứa
  • Dòng 2: Sau đó chúng ta có được .json()định dạng của dữ liệu cũng là một lời hứa
  • Dòng 3: Chúng tôi đã có dữ liệu hiện trả về JSON
  • Dòng 4: Chúng tôi đã nhận được lỗi trong trường hợp có bất kỳ

Cách xử lý lỗi trong API Fetch

Bây giờ chúng ta hãy xem cách chúng ta có thể xử lý lỗi từ API fetch mà không cần phụ thuộc vào từ khóa catch. Hàm fetch() sẽ tự động đưa ra lỗi cho lỗi mạng nhưng không phải cho lỗi HTTP như phản hồi 400 đến 5xx.

Tin tốt là fetch cung cấp một response.ok flag đơn giản cho biết yêu cầu không thành công hay mã trạng thái của phản hồi HTTP nằm trong phạm vi thành công.

Việc này rất đơn giản để thực hiện:

fetch("https://type.fit/api/quotes")
  .then((response) => {
    if (!response.ok) {
      throw Error(response.statusText);
    }
    return response.json();
  })
  .then((data) => console.log(data))
  .catch((err) => console.log(err));

Async/Await trong JavaScript

Async/Await cho phép chúng ta viết mã bất đồng bộ theo cách đồng bộ. Điều này có nghĩa là bạn không cần phải tiếp tục lồng các lệnh Callback.

Một hàm bất đồng bộ luôn trả về một Promise.

Bạn có thể đang đau đầu tự hỏi sự khác biệt giữa đồng bộ và không đồng bộ có nghĩa là gì. Nói một cách đơn giản, đồng bộ có nghĩa là các công việc được hoàn thành lần lượt. Không đồng bộ có nghĩa là các tác vụ được hoàn thành độc lập.

Lưu ý rằng chúng ta luôn có async ở phía trước hàm và chúng ta chỉ có thể sử dụng await khi chúng ta có async. Bạn sẽ sớm hiểu thôi!

Bây giờ chúng ta hãy triển khai mã API Fetch mà chúng ta đã làm trước đó bằng cách sử dụng async/await:

const fetchData = async () =>{
  const quotes = await fetch("https://type.fit/api/quotes");
  const response = await quotes.json();
  console.log(response);
}

fetchData();

Như thế này dễ đọc hơn nhiều phải không?

Bạn có thể tự hỏi làm thế nào chúng ta có thể xử lý lỗi với async/await. Vâng! Bạn sử dụng từ khóa try và catch:

const fetchData = async () => {
  try {
    const quotes = await fetch("https://type.fit/api/quotes");
    const response = await quotes.json();
    console.log(response);
  } catch (error) {
    console.log(error);
  }
};

fetchData();

Kết luận

Trong bài viết này, chúng ta đã tìm hiểu hơn 10 phương thức và khái niệm JavaScript mà mọi người nên hiểu rõ trước khi học React.

Có rất nhiều phương pháp và khái niệm khác mà bạn nên biết, nhưng đây là những phương pháp mà bạn có thể không thực sự chú ý khi học JavaScript. Đây là những điều quan trọng cần hiểu trước khi bạn học React.

Cảm ơn các bạn đã theo dõi.


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í