Now I have a problem in calling the API too many times and receiving error message 429 (too many requests) . I found a way to fix that error for my problem, by implementing some workarounds to limit multiple callbacks to the server.
In this article, I use Promise to request api. You probably have a basic understanding of Promise and have encountered it in many projects.
Promise is a JavaScript object used to perform asynchronous tasks and manage control flow. It represents a value that is not yet available at the time of promise creation , but will be returned once the task completes or fails.
Promise has two main states: "pending" and then "fulfilled" or "rejected".
Promises allow you to handle asynchronous code more easily by using .then() to define actions when the promise completes or .catch() to handle errors when the promise fails. This helps create more readable and manageable code when working with asynchronous tasks such as calling APIs, downloading documents from the network, or performing concurrent tasks.
For example:
// Tạo một Promise để gọi API
const fetchData = () => {
return new Promise((resolve, reject) => {
// Giả sử đây là một tác vụ bất đồng bộ, ví dụ tải dữ liệu từ máy chủ
setTimeout(() => {
const data = { message: "Dữ liệu đã được tải thành công" };
// Giả sử tác vụ thành công
resolve(data);
// Hoặc nếu tác vụ thất bại:
// reject("Lỗi xảy ra khi tải dữ liệu");
}, 2000);
});
};
// Sử dụng Promise để gọi API và xử lý dữ liệu
fetchData()
.then((data) => {
console.log("Dữ liệu đã được tải xong:", data.message);
})
.catch((error) => {
console.error("Lỗi khi tải dữ liệu:", error);
});
You can read more here: Promise
Resolve the following problem:
- Get categories data, from the api, https://dummyjson.com/products/categories , put it into the arr_categories array , then we will put the arr_categories array , display it on the website
let arr_categories = [];
const categories = fetch(
`https://dummyjson.com/products/categories`
);
const categoriesResponse = await categories;
const categoriesData = await categoriesResponse.json();
- Install APIs for each category, for example: https://dummyjson.com/products/category/arr_categories[i] , use for loop for arr_categories array ,
let link_categories = [];
for (let i = 0; i < categoriesData.length; i++) {
arr_categories.push(categoriesData[i]);
//push url to array link categories
let link =
"https://dummyjson.com/products/category/" + categoriesData[i];
link_categories.push(link);
}
- After we have the list of api links in the link_categories array , we will use map to create fetch (url) , setting the timeout value for each fetch url
const timeout = 5000; // Timeout 5 seconds (you can adjust this)
const productPromises = link_categories.map((url) =>
Promise.race([
fetch(url).then((response) => response.json()),
new Promise((_, reject) =>
setTimeout(
() => reject(new Error("Request Timeout")),
timeout
)
),
]).then((responseBody) => responseBody.products)
);
- After the above step, we need to use promise to run all fetch api,
// we call array fetch categories
Promise.all(productPromises)
.then((products) => {
data_temp = data_temp.concat(products);
//after when , i have data, i will show data first to website
if(dem==0){
append_html(data_temp[0]);
}
//end show
})
.catch((err) => {
console.error("Failed to fetch data:", err);
});
Note here that I need to display the first data on the website for users to see. When you see the full code, it will be easier to visualize.
//after when , i have data, i will show data first to website
if(dem==0){
append_html(data_temp[0]);
}
Now we just need to iterate over the data
async function fetchDataAndUseIt(name, id) {
try {
await call_api(dem);
if (id == 0 && dem == 0) {
arr_categories.map((item, index) => {
$(".add-categories").append(
'<span class="text-white font-bold p-2 m-2 inline-block cursor-pointer bg-gray-400 rounded-md" onClick="fetchDataAndUseIt(\'' +
item +
"'," +
index +
')">' +
item +
"</span>"
);
dem++;
});
}
let mang = [];
if (name == null) {
mang = data_temp[0];
} else {
let index = arr_categories.findIndex((item) => item == name);
console.log("index", index);
mang = data_temp[index];
}
append_html(mang);
dem++;
} catch (err) {
console.error("Error:", err);
}
}
let append_html = (mang) => {
$(".add_product").html("");
let html = "";
for (let i = 0; i < mang.length; i++) {
html += `<tr class="text-center" >
<td class="border border-slate-300">${mang[i].id}</td>
<td class="border border-slate-300">${mang[i].title}</td>
<td class="border border-slate-300 text-center"><img src='${mang[i].thumbnail}' width="100px" height="100px"></td>
</tr>`;
}
$(".add_product").html(html);
};
fetchDataAndUseIt(null, 0);
In the above code we need to install the function fetchDataAndUseIt (null, 0); To insert the parameter value (n_ame, id_ ) click on the category , which calls the function again
Okay, it's Full Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"
integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
<script src="https://cdn.tailwindcss.com"></script>
<script>
let data_temp = [];
let arr_categories = [];
let call_api = async (dem) => {
//if demo==0 , i will call first
if (dem == 0) {
try {
const categories = fetch(
`https://dummyjson.com/products/categories`
);
const categoriesResponse = await categories;
const categoriesData = await categoriesResponse.json();
let link_categories = [];
for (let i = 0; i < categoriesData.length; i++) {
arr_categories.push(categoriesData[i]);
//push url to array link categories
let link =
"https://dummyjson.com/products/category/" + categoriesData[i];
link_categories.push(link);
}
const timeout = 5000; // Timeout 5 seconds (you can adjust this)
const productPromises = link_categories.map((url) =>
Promise.race([
fetch(url).then((response) => response.json()),
new Promise((_, reject) =>
setTimeout(
() => reject(new Error("Request Timeout")),
timeout
)
),
]).then((responseBody) => responseBody.products)
);
// we call array fetch categories
Promise.all(productPromises)
.then((products) => {
data_temp = data_temp.concat(products);
//after when , i have data, i will show data first to website
if(dem==0){
append_html(data_temp[0]);
}
//end show
})
.catch((err) => {
console.error("Failed to fetch data:", err);
});
return data_temp; // return array products
} catch (err) {
console.error("Failed to fetch data:", err);
throw err;
}
}
};
let dem = 0;
async function fetchDataAndUseIt(name, id) {
try {
await call_api(dem);
if (id == 0 && dem == 0) {
arr_categories.map((item, index) => {
$(".add-categories").append(
'<span class="text-white font-bold p-2 m-2 inline-block cursor-pointer bg-gray-400 rounded-md" onClick="fetchDataAndUseIt(\'' +
item +
"'," +
index +
')">' +
item +
"</span>"
);
dem++;
});
}
let mang = [];
if (name == null) {
mang = data_temp[0];
} else {
let index = arr_categories.findIndex((item) => item == name);
console.log("index", index);
mang = data_temp[index];
}
append_html(mang);
dem++;
} catch (err) {
console.error("Error:", err);
}
}
let append_html = (mang) => {
$(".add_product").html("");
let html = "";
for (let i = 0; i < mang.length; i++) {
html += `<tr class="text-center" >
<td class="border border-slate-300">${mang[i].id}</td>
<td class="border border-slate-300">${mang[i].title}</td>
<td class="border border-slate-300 text-center"><img src='${mang[i].thumbnail}' width="100px" height="100px"></td>
</tr>`;
}
$(".add_product").html(html);
};
fetchDataAndUseIt(null, 0);
</script>
</head>
<body>
<div class="mx-auto max-w-3xl">
<h2 class="text-red-500 text-xl p-2 font-bold">List Categories</h2>
<ul class="flex flex-row p-5 bg-gray-200 rounded-md">
<li class="add-categories"></li>
</ul>
<div class="w-full p-2">
<table class="w-full table">
<caption>
<h2 class="text-red-500 text-xl p-2 font-bold text-left">List Products</h2>
</caption>
<thead>
<tr>
<th class="border border-slate-300">ID</th>
<th class="border border-slate-300">name</th>
<th class="border border-slate-300">thumbnail</th>
</tr>
</thead>
<tbody class="add_product"></tbody>
</table>
</div>
</div>class
</body>
</html>
Demo:
The Article : Fetch Multiple API Using Promises. You Can Fix 429 (Too Many Requests)
Top comments (0)