如果所有迭代都返回空,则执行某些操作,如果其中一个迭代返回某些内容,则执行其他操作

If all iterations return empty do something and if 1 of the iterations returns something do something else

提问人:nb_nb_nb 提问时间:8/29/2023 更新时间:8/29/2023 访问量:48

问:

我有一个值数组,我需要遍历这些值以根据我从文本框中获取的值运行函数。

我的代码:

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

因此,如果匹配,我需要的响应是:d.datatruckID.value

[]
[]
[{...}]

这就是它进入语句的时候。if

另一个是当:

如果与我需要的不匹配,则响应为:truckID.value

[]
[]
[]

我的问题是当我有 时,即使有匹配项,它也会转到其他位置。当数组的长度至少 0 次迭代大于 1 次时,有没有办法编写 if 语句?如果所有迭代都返回长度为 0,则执行其他操作吗?else

JavaScript 数组 循环对象 Axios

评论

0赞 mykaf 8/29/2023
根据你的标题,我会考虑使用 [Array.some()(developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...)。
2赞 Barmar 8/29/2023
@mykaf 由于它调用的是异步函数,这很复杂。

答:

1赞 Barmar 8/29/2023 #1

将回调设置为异步函数,以便可以使用 .然后,您可以根据任何调用是否返回某些内容来设置变量。await

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

1赞 StriplingWarrior 8/29/2023 #2

如果您可以重写后面的 API 以获取所有三个值并返回批处理,那么您就不会进行多次往返,那将是理想的选择。但是假设你不能这样做,并且你可以等待所有的往返返回(否则你无法知道它们是否都是空的),你可以使用 Promise.all() 等到它们全部解决。axiosFunctionarr

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

此代码使用假设您只期望一个有效结果。如果可能有多个,您可以调整它以使用它。findfilter

1赞 Larry 8/29/2023 #3

这也取决于你打算如何遍历数组 - 确实想要:

  • 仅在第一场比赛中操作,或者
  • 对每场比赛进行手术

找到匹配项后,可以使用以下方法扩展示例:break

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

当找到匹配项时,请注意内部条件 - 这将防止对 的任何后续调用,这可能是也可能不是您想要的。breakaxiosFunction

以下是处理调用的几种方法,具体取决于您是要等待每个调用、获取第一个匹配结果还是获取所有匹配结果,使用 和 :async / awaitArray.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
});
1赞 Danziger 8/29/2023 #4

当您使用 发出多个请求时,您首先需要使用 Promise.allSettled() 或 Promise.all() 解析这些 promiseaxiosFunction

然后,您可以使用 Array.prototype.some() 或 Array.prototype.every() 来检查返回的数据,看起来您需要嵌套其中两个,因为您的结果是一个包含更多数组的数组。

下面是一个带有模拟 .输入一个结果的输入字段,或“未找到”的其他内容:axiosFunctionfoo

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>