Sao có thể làm chủ Async/Await với ví dụ thực tế
Bài đăng này đã không được cập nhật trong 5 năm
Giời thiệu
Async / await là một cách mới để viết mã bất đồng bộ. Nó được xây dựng dựa trên lời hứa, do đó, nó cũng non blocking.
Trước đây chúng ta chỉ có hai lựa chọn là callbacks và promies.
Callbacks
setTimeout(() => {
console.log('This runs after 1000 milliseconds.');
}, 1000);
Vấn đề của callbacks - callbacks hell
callbacks nồng nhau trông như thế này:
asyncCallOne(){
asyncCallTwo(){
asyncCallThree(){
asyncCallFour(){
asyncCallFive(){
asyncCallSix(){
asyncCallSeven(){
asyncCallEight(){
asyncCallNight(){
asyncCallTen(){
// do something here...
}
}
}
}
}
}
}
}
}
}
Callback Hell Là các callback được giọ sâu nhiều cấp như trên, nó sẽ gây khó hiểu và khó mà maintain được code.
Promises
const promiseFunction = new Promise((resolve, reject) => {
const add = (a, b) => a + b;
resolve(add(2, 2));
});
promiseFunction.then((response) => {
console.log(response);
}).catch((error) => {
console.log(error);
})
promiseFunction sẽ trả về một Promies là một tiến trình thực thi của hàm đó. Hàm resolve là tín hiệu để Promise kết thúc. Sau đó ta dùng .then() và .catch() lên promise function: then - trả về một callback nếu promise trả về kết quả thành công catch - trả về một callback nếu promise trả về lỗi.
Async Functions
Async function cho chúng ta một cú pháp ngắn gọn và rõ ràng cho phép cũng ta viết được code ngắn gọn hơn mà kết quả trả về cũng giống như với promies. Async không khác gì mấy so với promises. Async function được tạo bởi từ async trước function trông giống như:
const asyncFunction = async () => {
// Code
}
Asynchronous functions có thể 'dừng' với await, keyword mà chúng ta chỉ có thể sử dụng bên trong async function. Await trả về bất cứ thứ gì mà khi function xong. Sự khác nhau giữa promises và async/await:
// Async/Await
const asyncGreeting = async () => 'Greetings';
// Promises
const promiseGreeting = () => new Promise(((resolve) => {
resolve('Greetings');
}));
asyncGreeting().then(result => console.log(result));
promiseGreeting().then(result => console.log(result));
Async/Await trông giống như code đồng bộ, và code đồng bộ thì dễ hiểu hơn. Bây giờ là ví dụ thực tế.
Bộ chuyển đổi tiền tệ
Mô tả và thiết lập dự án
Chúng ta sẽ tạo một ví dụ đơn giản nhưng hữu dụng giúp chúng ta nắm dõ về Async/Await.
Chương trình sẽ lấy mã tiền tệ mà chúng tôi muốn chuyển đổi và mã tiền tệ chúng tôi muốn chuyển đổi, cũng như số tiền. Sau đó, chương trình sẽ đưa ra tỷ giá hối đoái chính xác dựa trên dữ liệu từ các API.
Trong ứng dụng này, chúng tôi sẽ nhận dữ liệu từ hai nguồn không đồng bộ:
- Currency Layer --- https://currencylayer.com Bạn cần phải đăng ký miễn phí để có thể sử dụng Khóa truy cập API. API này sẽ cung cấp cho chúng tôi dữ liệu cần thiết để tính tỷ giá hối đoái giữa các loại tiền tệ.
- untries — http://restcountries.eu/ -- API này sẽ cung cấp cho chúng ta thông tin về nơi có thể sử dụng loại tiền mà vừa chuyển đổi tiền của mình.
Bắt đầu với tạo thư mục mới và bắt đầu chạy với
npm init
, bỏ qua các bước, và cài đặt axois vơi dòng lệnhnpm i --save axios
. Tạo một file mới currency-converter.js Đầu tiên chúng ta khai báo axios:const axios = require('axios');
Hàm đầu tiên - Lấy dữ liệu bất đồng bộ
Chúng ta tạo một function có hai tham số truyền vào là fromCurrency và toCurrency.
const getExchangeRate = async (fromCurrency, toCurrency) => {}
Bây giờ chúng ta cần lấy dữ liệu. Với async / await, chúng ta có thể gán dữ liệu trực tiếp cho một biến; đừng quên đăng ký và nhập khóa truy cập chính xác của bạn.
const getExchangeRate = async (fromCurrency, toCurrency) => {
const response = await axios.get('http://data.fixer.io/api/latest? access_key=[yourAccessKey]&format=1');
}
dữ liệu trả về sẽ dưới dạng response.data.rates
nên có thể gán biến cho kết quả trả về:
const rate = response.data.rates;
Vì mọi thứ đang được chuyển đổi từ đồng euro, bên dưới, chúng tôi sẽ tạo ra một biến có tên là euro sẽ bằng 1 / đơn vị tiền tệ mà chúng tôi muốn chuyển đổi từ:
const euro = 1 / rate[fromCurrency];
Cuối cùng, để có được tỷ giá hối đoái, chúng tôi có thể nhân euro với loại tiền mà chúng tôi muốn chuyển đổi thành:
const exchangeRate = euro * rate[toCurrency];
Cuối cùng, hàm sẽ trông giống như thế này:
const getExchangeRate = async (fromCurrency, toCurrency) => {
const response = await axios.get('http://data.fixer.io/api/latest? access_key=[yourAccessKey]&format=1');
const euro = 1 / rate[fromCurrency];
const exchangeRate = euro * rate[toCurrency];
}
Hàm thứ hai - nhận giá trị quốc gia không đồng bộ
Chúng tôi sẽ tạo ra một hàm không đồng bộ sẽ lấy moneyCode làm đối số:
const getCountries = async (currencyCode) => {}
Như chúng ta đã thấy trước đây, chúng ta sẽ tìm nạp dữ liệu và gán nó cho một biến:
const response = await axios.get(`https://restcountries.eu/rest/v2/currency/${currencyCode}`);
giá trị trả về mảng giá trị name
return response.data.map(country => country.name);
cuối cùng hàm sẽ trông giống như sau:
const getCountries = async (currencyCode) => {
const response = await axios.get(`https://restcountries.eu/rest/v2/currency/${currencyCode}`);
return response.data.map(country => country.name);
}
Hàm thứ ba
Chúng ta tạo hàm gồm 3 tham số truyền vào fromCurrency, toCurrency, và amount
const convert = async (fromCurrency, toCurrency, amount) => {}
Đầu tiên chúng ta get currency data:
const exchangeRate = await getExchangeRate(fromCurrency, toCurrency);
Tiếp theo là dữ liệu các nước:
const countries = await getCountries(toCurrency);
Tiếp đến là chuyển đổi giá trị:
const convertedAmount = (amount * exchangeRate).toFixed(2);
Cuối cùng kết quả trả về:
return `${amount} ${fromCurrency} is worth ${convertedAmount} ${toCurrency}. You can spend these in the following countries: ${countries}`;
Tất cả kết hợp lại sẽ trông như thế này:
const convert = async (fromCurrency, toCurrency, amount) => {
const exchangeRate = await getExchangeRate(fromCurrency, toCurrency);
const countries = await getCountries(toCurrency);
const convertedAmount = (amount * exchangeRate).toFixed(2);
return `${amount} ${fromCurrency} is worth ${convertedAmount} ${toCurrency}. You can spend these in the following countries: ${countries}
}
Thêm try/catch để xử lý lỗi cho hàm đầu tiên
const getExchangeRate = async (fromCurrency, toCurrency) => {
try {
const response = await axios.get('http://data.fixer.io/api/latest?access_key=f68b13604ac8e570a00f7d8fe7f25e1b&format=1');
const rate = response.data.rates;
const euro = 1 / rate[fromCurrency];
const exchangeRate = euro * rate[toCurrency];
return exchangeRate;
} catch (error) {
throw new Error(`Unable to get currency ${fromCurrency} and ${toCurrency}`);
}
}
Tương tự với hàm thứ hai:
const getCountries = async (currencyCode) => {
try {
const response = await axios.get(`https://restcountries.eu/rest/v2/currency/${currencyCode}`);
return response.data.map(country => country.name);
} catch (error) {
throw new Error(`Unable to get countries that use ${currencyCode}`);
}
};
Cuối cùng là gọi function
convertCurrency('USD', 'HRK', 20)
.then((message) => {
console.log(message);
}).catch((error) => {
console.log(error.message);
});
Trên đây là một ví dụ rất đơn giản về sử dụng async/await trong thực tế Tham khảo: https://medium.freecodecamp.org/how-to-master-async-await-with-this-real-world-example-19107e7558ad
All rights reserved