在 uni-app 中切换页面后,怎样中断 onShow 生命周期中的异步函数?

image.png

onShow() 中有很多的函数调用和异步调用,并且很多很容易出错。当我切换到下一个页面的时候我发现
这个页面 onShow() 里面代码仍在执行,有什么好的办法中断吗?

目前能想到的是写一个 show 的状态,页面隐藏时改为 false,然后每个函数调用前加个判断,感觉有点笨😂。

阅读 1.1k
avatarAI BotBETA

在uni-app中,onShow 生命周期函数在页面显示时会被调用,而且其中的异步操作会继续执行,即使你已经切换到了其他页面。如果你希望在某些条件下中断这些异步操作,确实需要采取一些策略来管理这些异步任务。

你提到的通过设置一个 show 状态,并在每个异步操作前检查这个状态的方法是一个可行的解决方案。虽然这种方法可能看起来有些繁琐,但它确实能够有效地控制异步操作的执行。

这里是一个简化的示例,展示如何使用这种方法来管理 onShow 中的异步操作:

export default {
  data() {
    return {
      isShowing: true, // 控制页面是否显示的标志位
    };
  },
  onShow() {
    if (!this.isShowing) return; // 如果页面不处于显示状态,则不执行后续操作

    this.doSomeAsyncTask1();
    this.doSomeAsyncTask2();
    // ... 其他异步操作
  },
  onHide() {
    this.isShowing = false; // 当页面隐藏时,设置标志位为false
  },
  onShow() {
    this.isShowing = true; // 当页面显示时,设置标志位为true
  },
  methods: {
    doSomeAsyncTask1() {
      if (!this.isShowing) return; // 在异步操作前检查标志位

      // 执行异步操作...
    },
    doSomeAsyncTask2() {
      if (!this.isShowing) return; // 在异步操作前检查标志位

      // 执行异步操作...
    },
    // ... 其他异步方法
  },
};

这种方法的优点是简单直接,易于理解。不过,如果你有很多异步操作需要管理,并且希望在多个页面之间共享这些逻辑,那么你可能需要考虑使用更高级的技术,如使用 Vuex 管理全局状态,或者使用专门的库来管理异步任务和取消操作。

注意:在实际应用中,确保在组件销毁时取消所有未完成的异步操作,以避免潜在的内存泄漏和其他问题。这可以通过在 beforeDestroydestroyed 生命周期钩子中取消这些操作来实现。

2 个回答

看下这个案例,可以实现你这个需求。

function executeAsyncFunctions(asyncFunctions) {
  // 标志变量,用于控制是否停止执行剩余的异步函数
  let stopExecution = false;

  // 异步函数执行器
  async function executeAsyncFunction(asyncFunction) {
    if (!stopExecution) {
      try {
        await asyncFunction();
      } catch (error) {
        console.error(error);
      }
    }
  }

  // 执行异步函数的入口函数
  async function execute() {
    for (const asyncFunction of asyncFunctions) {
      await executeAsyncFunction(asyncFunction);
    }
  }

  // 停止执行剩余异步函数的函数
  function stopExecutionOfRemainingFunctions() {
    stopExecution = true;
  }

  return {
    execute,
    stopExecutionOfRemainingFunctions,
  };
}

// 异步函数1
async function asyncFunction1() {
  console.log('Executing asyncFunction1');
  await new Promise((resolve) => setTimeout(resolve, 1000));
  console.log('asyncFunction1 completed');
}

// 异步函数2
async function asyncFunction2() {
  console.log('Executing asyncFunction2');
  await new Promise((resolve) => setTimeout(resolve, 1000));
  console.log('asyncFunction2 completed');
}

// 异步函数3
async function asyncFunction3() {
  console.log('Executing asyncFunction3');
  await new Promise((resolve) => setTimeout(resolve, 1000));
  console.log('asyncFunction3 completed');
}

// 创建异步函数数组
const asyncFunctions = [asyncFunction1, asyncFunction2, asyncFunction3];

// 创建异步函数执行器
const executor = executeAsyncFunctions(asyncFunctions);

// 执行异步函数
executor.execute();

// 在某个指定时机停止执行剩余异步函数
setTimeout(() => {
  executor.stopExecutionOfRemainingFunctions();
  console.log('Execution stopped');
}, 2000);

在两秒后停止执行剩余异步函数,执行结果如下:
image.png

可以把异步操作看做一个一个的任务,然后生成一个任务队列,迭代这个任务队列时判断一下状态,本质上和每个函数调用前加个判断差不多

推荐问题