开发者问题收集

我想一次单击调用两个函数并确保它们能依次运行

2020-03-24
753

我想得到帮助来解决我试图解决的一个问题,所以问题是我必须调用两个 API url。第二个依赖于第一个(在第一次获取中,我获取了一些基本信息,包括 id,在第二次获取中,我想根据第一次获取的 id 获取数据)。 我总是得到这个错误: Uncaught TypeError:无法读取未定义的属性“length” 可能我的方法不正确。我尝试了一些方法,比如将第二个函数放在第一个函数中,我尝试在不使用异步的情况下执行此操作,它仅在我有两个不同的按钮时才有效。 我猜是异步导致了这个问题。(它试图在响应之前获取长度) 请帮助我解决这个问题。我很想了解一些关于方法的见解或任何解决方法。 提前谢谢。 这是有问题的代码

//recipies by ingredients array
var displayData = [];
//full recipies array
var displayRecipes = [];

document.getElementById("search").addEventListener("click", function () {
  var l = document.getElementsByClassName("ingInput").length
  var ing = document.getElementById('id').value
  var ing1 = ''
  //getting all the values from the inputs so i can search it in the api url
  for(var i = 1; i<l ;i++){
    ing1 += ',' + document.getElementsByClassName("ingInput")[i].value 
  }
  //async get request for the api url 
 async function postData(url = '') {
    const response = await fetch(url, {
      method: 'GET', // *GET, POST, PUT, DELETE, etc.
      headers: {
        'Content-Type': 'application/json'
        // 'Content-Type': 'application/x-www-form-urlencoded',
      },

    });
    return response.json(); // parses JSON response into native JavaScript objects
  }
  //the api url with the inputs values for searching by ingredeints
  postData('https://api.spoonacular.com/recipes/findByIngredients?ingredients='+ ing + ing1 + '&number=10&apiKey=API_KEY')
    .then((data) => {
      displayData.push(data); // JSON data parsed by `response.json()` call
      console.log('done')
    });

})

//second func
document.getElementById("search").addEventListener("click", function () {
//trying to get data from this array, here i have error.
  var l = displayData[0].length
  var ids = []
  for(var i = 0; i<l ;i++){
    ids.push(displayData[0][i].id) 
  }

  async function postData(url = '') {
    // Default options are marked with *
    const response = await fetch(url, {
      method: 'GET', // *GET, POST, PUT, DELETE, etc.
      headers: {
        'Content-Type': 'application/json'
        // 'Content-Type': 'application/x-www-form-urlencoded',
      },

    });
    return await response.json(); // parses JSON response into native JavaScript objects
  }

  postData('https://api.spoonacular.com/recipes/informationBulk?ids='+ids.toString()+'&apiKey=API_KEY')
    .then((data) => {
      displayRecipes.push(data); // JSON data parsed by `response.json()` call
      console.log(displayRecipes)
    });

})```
2个回答

如果只有第一次获取数据,您才可以进行第二次获取。这样,当没有数据时,按钮会获取初始数据。如果数据已经存在,它会获取附加信息。因此,您有一个侦听器:

 document.getElementById( "search" ).addEventListener( "click", function () {
    if ( displayData.length === 0 ) {
        // Call first function 
    } else {
        // Call second function
    }
 })
PJohnson
2020-03-24

我找到了一个解决方案,我不确定这是否是最好的方法,但对我来说效果很好。 所以 dom 看起来像这样: (我在搜索按钮中添加了 onclick)

<div id="container">
        <!-- first input for the first ingrediant you can search -->
        <input type="text" class="ingInput" id="id" placeholder="ingrediant" onfocus="auto(this)">
    </div>
    <!-- search button, first bring the recipies based on ingredient, then the full recipies based on ids from the first fetch data -->
    <button  id="search" onclick="asyncCall()">Search</button>

    <!-- add new input for more ingrediant -->
    <button id="add" onclick="add()">Add</button>

    <!-- display the element i have created from the data i have -->
    <div id="display">

    </div>
    <!-- for jquery pagination -->
<button id="btn_prev">Prev</button>
<button id="btn_next">Next</button>
page: <span id="page"></span>

以及用于获取数据的 javascript(首先从第一个 api 链接,然后从第二个 api 链接):

//recipies by ingredients array
var displayData = [];

//full recipies array
var displayRecipes = [];

async function search(){

  var l = document.getElementsByClassName("ingInput").length
  var ing = document.getElementById('id').value
  var ing1 = ''
  //getting all the values from the inputs so i can search it in the api url
  for(var i = 1; i<l ;i++){
    ing1 += ',' + document.getElementsByClassName("ingInput")[i].value 
  }

  //the api url with the inputs values for searching by ingredeints
 await fetch('https://api.spoonacular.com/recipes/findByIngredients?ingredients='+ ing + ing1 + '&number=10&apiKey=API_KEY', {
    method: 'GET', // *GET, POST, PUT, DELETE, etc.
    headers: {
      'Content-Type': 'application/json'
      // 'Content-Type': 'application/x-www-form-urlencoded',
    }
  }).then(res => res.json())
    .then((data) => {
      displayData.push(data); // JSON data parsed by `response.json()` call
      console.log('done')
    });   
}

async function getRecipes(){
  var l = displayData[0].length
  var ids = []
  for(var i = 0; i<l ;i++){
    ids.push(displayData[0][i].id) 
  }
  await fetch('https://api.spoonacular.com/recipes/informationBulk?ids='+ids.toString()+'&apiKey=API_KEY',{
      method: 'GET', // *GET, POST, PUT, DELETE, etc.
      headers: {
        'Content-Type': 'application/json'
        // 'Content-Type': 'application/x-www-form-urlencoded',
      }
    })
    .then(res => res.json())
    .then((data) => {
      displayRecipes.push(data); // JSON data parsed by `response.json()` call
      console.log(displayRecipes)
    });   
}

async function asyncCall() {
  console.log('calling');
  const resultSearch = await search();
  console.log('done await search');

  console.log('calling2');
  const resultRecipies = await getRecipes();
  console.log('done await recipes');

}```
Elna Haim
2020-03-25