skip to Main Content

I have an array of values, I need to loop through those to run a function based on a value I get from a textbox.

My code:

<label for="truck">Truck:</label>
<input type="text" id="truck" name="truck">
<button type="button" id="myButton">Click Me!</button>

const truckBtn = document.getElementById("myButton");
const truckID = document.getElementById("truck");
truckBtn.addEventListener("click", () => {

  let arrs = ["one", "two", "three"];

  for (const arr of arrs) {
     axiosFunction(arr, truckID.value).then(d=> {
      console.log(d.data);
      if (d.data.length > 0) {
         // do something
      } else alert("Not Found");
   });
  }
});

So d.data if truckID.value matches what I need the response is:

[]
[]
[{...}]

That’s when it goes into the if statement.

The else is when:

if truckID.value does not match what I need the response is:

[]
[]
[]

My issue is when I have the else, it goes to the else even when there is match. Is there way to write an if statement when the length of the array is greater than 0 for at least 1 iteration? And do the else if all the iterations return a length of 0?

4

Answers


  1. Make the callback an async function so you can use await. Then you can set a variable based on whether any of the calls return something.

    truckBtn.addEventListener("click", async() => {
      let arrs = ["one", "two", "three"];
      let found = false;
      for (const arr of arrs) {
        let d = await axiosFunction(arr, truckID.value);
        console.log(d.data);
        if (d.data.length > 0) {
          found = true;
          // do stuff
        }
      }
      if (!found) {
        console.log("Not found!");
      }
    });
    Login or Signup to reply.
  2. It would be ideal if you could rewrite the API behind your axiosFunction to take all three arr values and return a batch, so you’re not making multiple round-trips. But assuming you can’t do that, and you’re okay with waiting for all the round-trips to return (otherwise you can’t know whether they all returned empty), you can use Promise.all() to wait until they’re all resolved.

    <label for="truck">Truck:</label>
    <input type="text" id="truck" name="truck">
    <button type="button" id="myButton">Click Me!</button>
    
    truckBtn.addEventListener("click", () => {
    
      let arrs = ["one", "two", "three"];
      Promise.all(arrs.map(arr => axiosFunction(arr, truckID.value)))
        .then(results => {
          console.log(results.map(d => d.data)); // [[], [], [...]]
          const firstValidResult = results.find(d => d.data.length > 0);
          if(firstValidResult) {
             // do something with firstValidResult.data
          } else alert("Not Found");
        });
    });
    

    This code uses find assuming you’re only expecting one valid result. You could tweak it to use filter if there might be several.

    Login or Signup to reply.
  3. This also depends on how you intend on looping through the array – do want to:

    • operate on the first match only, or
    • operate on every match

    Your example can be extended by using break once you find the match:

    const truckBtn = document.getElementById("myButton");
    const truckID = document.getElementById("truck");
    
    truckBtn.addEventListener("click", () => {
      let arrs = ["one", "two", "three"];
    
      for (const arr of arrs) {
         axiosFunction(arr, truckID.value).then(d=> {
          console.log(d.data);
          if (d.data.length > 0) {
             // do something
             break; // don't perform anymore work once we have any match
          } else alert("Not Found");
       });
      }
    });
    
    

    Notice the break inside the condition when the match is found – this will prevent any subsequent calls to axiosFunction, which may or may not be what you want.

    Below are a few ways of handling the calls depending on whether you want to wait for each call, get the first matching result, or get all the matching results, using async / await and Array.map:

    const arrs = ["one", "two", "three"];
    
    // execute axiosFunction calls in sequence, like using a for loop
    truckBtn.addEventListener("click", async () => {
      const matches = arrs.map(async x => await axiosFunction(x, truckID.value))
            .filter(x => x.data.length > 0);
      const match = matches.find(Boolean); // get the first truthy result
    
      // do something if match is not null
    }
    
    
    // execute all axiosFunction calls in parallel
    truckBtn.addEventListener("click", async () => {
      const promises = arrs.map(x => axiosFunction(x, truckID.value));
      // get all matches
      const matches = await Promise.all(promises)
                        .filter(x => x.data.length > 0);
      const match = matches.find(Boolean); // get the first truthy result
    
      // do something if match is not null
    }
    
    // execute axiosFunction calls in parallel, waiting for the first to resolve
    truckBtn.addEventListener("click", async () => {
      const promises = arrs.map(x => axiosFunction(x, truckID.value));
      const firstResolved = await Promise.race(promises);
      const match = firstResolved.data.length > 0 ? firstResolved : null;
    
      // do something with match
    });
    
    // execute axiosFunction calls in parallel, handling if none of them resolve
    truckBtn.addEventListener("click", async () => {
      const promises = arrs.map(x => axiosFunction(x, truckID.value));
      let match = null;
    
      try {
        const firstResolved = await Promise.any(promises);
        match = firstResolved.data.length > 0 ? firstResolved : match;
      } catch (err) {
        // no promise resolved
      }
      
      // do something with match
    });
    
    Login or Signup to reply.
  4. As you are making multiple requests with axiosFunction, you first need to resolve those promises, using Promise.allSettled() or Promise.all().

    Then, you can use Array.prototype.some() or Array.prototype.every() to check the returned data, and it looks like you need to nest two of them as your result is an array that contains more arrays.

    Here’s an example with a mocked axiosFunction. Type foo in the input field for one result, or something else for "not found":

    const searchButton = document.getElementById("searchButton");
    const truckInput = document.getElementById("truckInput");
    
    const items = ["one", "two", "three"];
    
    function axiosFunction(array, value) {
      return Promise.resolve({
        data: value === 'foo' ? array.map((_, i) => [{}]) : array.map(_ => []),
      })
    }
    
    searchButton.addEventListener("click", async () => {
      const { value } = truckInput;
     
      // Make all requests in parallel:
      const promises = items.map((item) => {
        return axiosFunction(items, value)
      })
      
      // Wait for all of them to resolve:
      const results = await Promise.allSettled(promises);
      
      // Extract the data part from the results:
      const resultsData = results.map(result => result.value.data);
      
      console.log(resultsData);
      
      // Iterate over the data from each request:
      const found = resultsData.some((resultData) => {
        // Itereate over the array items returned by each request:
        return resultData.some((resultItem) => {
          // And check if any of them contains something:
          return resultItem.length > 0;
        });
      })
      
      if (found) {
        alert("Found!");
      } else {
        alert("Not Found...");
      }
    });
    <label for="truck">Truck:</label>
    <input type="text" id="truckInput">
    <button type="button" id="searchButton">Search</button>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search