函数不应该异步运行

时间:2019-08-02 07:05:56

标签: javascript reactjs firebase react-native

我正在实现一些功能,其中从firebase检索一些array类型的数据, 然后从该数组中搜索特定元素,如果存在, 我想中止该函数并返回到调用者。 (本机应用程序)

代码如下:

ref.get().then(snapshot => {
    const personArr = snapshot.data().winPerson;

    ...

    if (personArr != undefined) {
      personArr.forEach(item => {
        if (item == uid.uid) {
          alert(`already subscribed`);
          return;
        }
      });

      if (prop.first.length != 0) {
        uploadHelper(ref, prop, "first");
      }

     ...
    }
});

我使用forEach遍历数组,看看是否有匹配的元素。如果匹配,则它应发出警报并返回调用方函数,而无需运行下面的后续代码

if (prop.first.length != 0) {
        uploadHelper(ref, prop, "first");
      }

但是,假设元素确实存在于数组中, 该代码同时运行警报和uploadHelper函数(通过日志检查)。首先,我认为forEach是异步函数,因此在返回之前先执行uploadHelper; 但是,forEach不是异步函数(经过一些谷歌搜索)。

我不知道为什么如果代码落入if(item == uid.uid)条件并返回,则为什么uploadUpper运行。

感谢您的帮助。谢谢

4 个答案:

答案 0 :(得分:2)

它返回到调用者函数:) forEach()正在与每个元素一起调用函数。因此,您返回的只是该元素的功能。

我想您想在for of循环。想要进行函数式编程的人想使用.forEach,但是使用for of可以达到与.forEach相同的功能效果(不必编制索引,没有副作用)并且可能更易于使用。 (如果要在每个元素之间等待的地方编写异步代码,则forEach也有问题)

所以,像下面这样重写代码:

for (const item of personArr) {
    if (item == uid.uid) {
      alert(`already subscribed`);
      return;
    }
  }

答案 1 :(得分:1)

首先,您无法停止forEach。它将始终针对数组的每个元素运行,然后继续执行代码。返回值表明您当前正在迭代的元素将更改为您的返回值。

如果要停止执行,可以使用for-in循环或通用的for循环。

答案 2 :(得分:1)

改为使用此

for (let item of personArr) {
    if (item == uid.uid) {
        alert(`already subscribed`);
        break;
    }
}

forEach无法中断,这就是为什么您需要使用for并将其中断的原因。在forEach返回中意味着继续下一个索引而不处理下面的代码不会停止循环

答案 3 :(得分:1)

forEach处理程序也是一个函数。 (item => ...是箭头函数)因此,从personArr.forEach()内部返回并不会实际上阻止其余函数的执行。

因此,无论.forEach()做什么,if (prop.first.length != 0)都将得到检查。

如果目标是仅在未找到uid时运行uploadHelper,则需要稍微更改结构。 像这样:

ref.get().then(snapshot => {
    const personArr = snapshot.data().winPerson;

    ...

    if (personArr != undefined) {
      const match = personArr.find( item => item === uid.uid );
      if ( match ) alert(`already subscribed`);
      else if (prop.first.length != 0) {
        uploadHelper(ref, prop, "first");
      }
      // else { /* some other defualt case ? */ 
     ...
    }
});

如果item实际上与uid.uid的值相同,则您甚至可以使其更简单:

如果personArr.includes( uid.uid )uid.uid内,

personArr应该返回true。