简体   繁体   English

异步等待函数未在事件侦听器中执行

[英]Async await function not executing within an event listener

I'm trying to make a call to the Trip Advisor API and return some data using an async/await function.我正在尝试调用 Trip Advisor API 并使用 async/await 函数返回一些数据。

The async/await function is defined in a file named req.js and the code is below: async/await 函数定义在一个名为 req.js 的文件中,代码如下:

const findRest = async (reviews, closed) => {
  const respond = await fetch(
    "https://tripadvisor1.p.rapidapi.com/restaurants/list-by-latlng?limit=30&currency=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:此代码位于名为 app.js 的文件中,如下所示:

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:供参考的是这里的 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.当我在 app.js 文件中运行 findRest 函数时,但在事件侦听器之外并作为静态数据传入参数时,它执行查找并将所有请求的数据打印到控制台。 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.就像我说的,它在事件侦听器之外工作正常,但我尝试将 forEach 更改为 map 并且仍然没有返回任何内容。 Can someone please help!有人可以帮忙吗!

Answer回答

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. Array.forEach(callback)仅在数组包含元素时执行回调。

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).它可能为空的原因是restaurant.is_closed的过滤器可能需要一个布尔值,而您传入​​一个字符串(输入元素的值是一个字符串)。

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'.否则,您必须查看字符串输入是否与“真”或“假”匹配。

Code itself代码本身

The findRest contains unnecessary awaits. findRest包含不必要的等待。 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&currency=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您还可以在 eventListener 回调中使用 async/await,创建更清晰的代码

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)
  }
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM