Reputation: 37
I'm trying to make a call to the Trip Advisor API and return some data using an async/await function.
The async/await function is defined in a file named req.js and the code is below:
const findRest = async (reviews, closed) => {
const respond = await fetch(
"https://tripadvisor1.p.rapidapi.com/restaurants/list-by-latlng?limit=30¤cy=EUR&distance=2&lunit=km&lang=en_US&latitude=53.3498&longitude=-6.2603",
{
method: "GET",
headers: {
"x-rapidapi-host": "tripadvisor1.p.rapidapi.com",
"x-rapidapi-key": "x-rapidapi-key"
}
}
);
if (respond.status === 200) {
let data = await respond.json();
let newData = await data.data;
let data1 = await newData.filter(
review => parseInt(review.num_reviews) >= reviews
);
let data2 = await data1.filter(close => close.is_closed == closed);
return data2;
} else {
throw new Error("Could not provide results within specified parameters");
}
};
This is then called when an event listener fires by clicking a button in a small form. This code is in a file named app.js and is below:
document.getElementById("subButton").addEventListener("click", function(e) {
const userReviews = parseInt(document.querySelector(".userRev").value);
const userClose = document.querySelector(".userClose").value;
e.preventDefault();
console.log("click");
console.log(e.target.id);
findRest(userReviews, userClose)
.then(data =>
data.forEach(element =>
console.log(
`${element.name} matches your search criterea and is located at ${element.address}
To make a booking, please call ${element.phone}`
)
)
)
.catch(err => console.log(err));
});
And for reference here is the HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>API Tester</title>
<meta name="author" content="Phil My Glass" />
<meta
name="description"
content="An app to help me practice my API calling"
/>
</head>
<body>
<header>
<h1>What Restaurant?</h1>
</header>
<main>
<form id="form">
<input id="userRev" class="userRev" /><br />
<input id="userClose" class="userClose" />
<button id="subButton" class="subButton" type="submit">Find!</button>
</form>
</main>
</body>
<script src="req.js" type="text/Javascript"></script>
<script src="app.js" type="text/Javascript"></script>
</html>
When I run the findRest function within the app.js file, but outside the event listener and pass in the arguments as static data it executes just find and prints all the requested data to the console. As soon as I try and run it within the event listener nothing happens. No returned data printing, no error and it's killing me why.
Like I said, it works fine outside the event listener, but I've tried changing the forEach to map and still nothing is being returned. Can someone please help!
Upvotes: 2
Views: 6186
Reputation: 1426
Judging by the comments and your replies: the reason why nothing is a happening is because the data is an empty array.
Array.forEach(callback)
only executes the callback when the array contains elements.
The reason why it might be empty is that the filter for restaurant.is_closed
probably expects a boolean, whereas you pass in a string (the value of an input element is a string).
It's better to use a checkbox to see if it's checked instead. Otherwise you have to see if the string input matches with 'true' or 'false'.
The findRest
contains unnecessary awaits.
You should define it as
async function findRest(reviews, closed) {
const response = await fetch(
"https://tripadvisor1.p.rapidapi.com/restaurants/list-by-latlng?limit=30¤cy=EUR&distance=2&lunit=km&lang=en_US&latitude=53.3498&longitude=-6.2603",
{
method: "GET",
headers: {
"x-rapidapi-host": "tripadvisor1.p.rapidapi.com",
"x-rapidapi-key": "x-rapidapi-key"
}
}
);
if (response.status === 200) {
// The only async call is casting the response to a JavaScript object
const json = await response.json();
console.log(json);
const data = json.data;
// Filtering the array is not async
return data.filter((restaurant) => {
// Adding some additional debugs to prove my hypothesis right
const hasEnoughReviews = restaurant.num_review >= reviews;
const isClosed = restaurant.is_closed === closed;
console.log(`review debug: ${typeof restaurant.num_review}, ${typeof reviews} -> output: ${hasEnoughReviews}`);
console.log(`closed debug: ${typeof restaurant.is_closed}, ${typeof closed} -> output: ${isClosed}`)
return hasEnoughReviews && isClosed
})
} else {
throw new Error("Could not provide results within specified parameters");
}
}
You can also use the async/await in your eventListener callback, creating cleaner code
document.getElementById("subButton").addEventListener("click", async (e) => {
const userReviews = parseInt(document.querySelector(".userRev").value);
// Judging by the filter in the findRest, this should be a boolean?
const userClose = document.querySelector(".userClose").value;
e.preventDefault();
console.log("click");
console.log(e.target.id);
try {
const restaurants = await findRest(userReviews, userClose);
// I think your issue is that restaurants is an empty array
console.log(restaurants)
restaurants.forEach(restaurant => {
console.log(`${restaurant.name} matches your search criterea and is located at ${restaurant.address}
To make a booking, please call ${restaurant.phone}`)
})
} catch (err) {
console.log(err)
}
});
Upvotes: 2