Vue页面跳转与异步逻辑(执行uni.reLaunch跳转后接口仍然请求并弹出uni.showModal)

在uniapp中使用uni.showModal的时候,当页面使用uni.reLaunch切换到其他页面面之后,原页面已经被关闭了,但是接口还在执行,执行成功之后弹出uni.showModal。

为了测试这个问题,我们先执行uni.reLaunch跳转,再定义一个计时器来弹出uni.showModal

uni.reLaunch({
        url:'/pages/homePage/index'
    })
    setTimeout(() => {
        uni.showModal({ title: "系统提示",content:"测试提示!" });
    }, 10000)

跳转之后,uni.showModal依旧可以在新页面弹出,我们来分析一下切换其他页面为什么还能弹出uni.showModal

1.uni.showModal

uni.showModal是uni-app提供的API,用于在当前页面显示一个模态弹窗
官网说明:在非H5端,本章的所有弹出控件都是原生控件,层级最高,可覆盖video、map、tabbar等原生控件。(层级高)

2.uni.reLaunch(OBJECT)

uni.reLaunch(OBJECT)官网说明关闭所有页面,打开到应用内的某个页面
所以原页面已经被关闭,经测试确实已关闭

3.JavaScript执行环境

setTimeout 是 Web API 的一部分,它在浏览器的主线程中运行,即使切换到其他页面,只要当前页面实例没有被销毁,定时器仍然会继续执行

4.Vue页面生命周期

当使用 uni.navigateTo 或类似方法跳转到其他页面时,当前页面实际上并没有被销毁,页面实例仍然存在于内存中,所以定时器回调函数依然有效

5.Vue页面跳转与异步逻辑清理

1. 页面跳转与异步任务的关系
  • 页面跳转 ≠ 代码执行环境销毁

    • 页面跳转只是改变了视图层的显示
    • JavaScript执行环境仍然存在,除非页面被销毁
  • 异步任务独立于页面生命周期

    • setTimeoutPromisefetch等异步操作一旦启动就会继续执行
    • 即使页面已经跳转或隐藏,这些任务仍在事件循环中等待执行
2. 不同跳转方式的行为差异
跳转方法 页面状态 异步任务
uni.navigateTo 页面隐藏,实例保留 异步任务继续执行
uni.redirectTo 页面销毁 异步任务仍会执行
uni.reLaunch 所有页面销毁 异步任务仍可能执行
uni.switchTab 非tab页面被销毁 异步任务仍会执行
3.为什么页面销毁后异步任务仍执行
  • JavaScript 事件循环机制:
    • 当您调用 setTimeout 时,回调函数立即被添加到事件循环的任务队列中
    • 即使后续页面被销毁,这个任务仍然在队列中等待执行
    • JavaScript 是单线程的,任务一旦加入队列就会被执行
  • 内存中的任务队列:
    • 异步任务(包括定时器)存储在浏览器/运行环境的任务队列中
    • 页面销毁只是移除了页面的 DOM 和 Vue 组件实例
    • 但已经在事件循环中的任务并不依赖于页面实例的存在

6.JavaScript 的基本特性

  1. JavaScript 执行环境与异步任务
    任务队列机制
    JavaScript 使用事件循环(Event Loop)处理异步任务
    setTimeout 等异步操作会将回调函数放入任务队列
    任务队列独立于页面 DOM 结构和组件实例存在
  2. 页面销毁的实质
    页面销毁 ≠ JavaScript 执行环境销毁
    页面销毁只是移除了 DOM 元素和 Vue 组件实例
    浏览器的 JavaScript 执行环境仍然运行
    全局变量和已经启动的异步任务继续在事件循环中等待执行

这是 JavaScript 的核心特性之一:异步任务的生命周期独立于创建它们的组件或页面。开发者必须显式地管理这些异步任务,确保在不需要时进行清理,避免内存泄漏和意外行为。

总结:

无论使用 uni.redirectTo、uni.reLaunch 还是 uni.switchTab,页面销毁都不会影响已经加入事件循环的异步任务。这是 JavaScript 的基本特性而非bug,开发者必须手动管理这些异步任务的生命周期。

7.关于事件循环和Vue单页面的关系

1. 事件循环机制
  • 执行流程如下:
    • 调用 uni.reLaunch - 这是一个异步API调用,会被添加到任务队列中
    • 调用 setTimeout - 这个定时器回调也会被添加到任务队列中
    • 函数执行完毕 - 当前执行栈清空
    • 事件循环处理任务 - 事件循环会按照顺序处理队列中的任务
    • 关键点是:这两个操作都被添加到了事件循环的任务队列中,并且都会被执行。
2. Vue单页应用的影响
  • 在uni-app这样的单页应用框架中:
    • 页面切换 ≠不等于 页面卸载
    • 页面切换只是改变了路由和组件的显示状态
    • Vue组件实例可能仍然存在于内存中
    • 组件的执行上下文并未被销毁
    • JavaScript执行环境持续存在

8. Vue SPA 的基本特征

1.单页面实例

整个应用运行在单一的HTML页面中
页面切换实际上是组件的挂载和卸载
JavaScript运行环境始终保持活跃状态

// Vue组件生命周期与异步任务
created() {
  // 组件创建时启动异步任务
  this.timer = setTimeout(() => {
    // 即使组件被销毁,这个回调仍会执行
  }, 10000)
},
beforeDestroy() {
  // 需要手动清理异步任务
  clearTimeout(this.timer)
}
2. uni-app 中 Vue SPA 的特殊性

页面作为组件

// 每个页面实际上是一个Vue组件
defineOptions({
  name: 'mine',  // 页面组件名称
})

// 页面跳转 = 组件切换
uni.reLaunch({
  url:'/pages/homePage/index'  // 切换到另一个Vue组件
})
3. 与传统多页面应用的对比
特性 Vue SPA 传统多页面应用
JavaScript环境 持续存在 页面跳转后重置
异步任务生命周期 独立于页面 随页面销毁而终止
内存管理 需手动清理 自动清理
总结:

Vue单页应用的架构使得JavaScript执行环境持续存在,页面切换只是组件的挂载/卸载操作。因此,异步任务的生命周期独立于页面组件的生命周期,需要开发者手动管理这些任务的清理工作。这是Vue SPA的重要特性,理解这一点对于避免内存泄漏和意外行为至关重要。

9.总结:

Vue单页应用的架构使得JavaScript执行环境持续存在,整个应用运行在同一个JavaScript上下文中
定时器等异步任务不受页面切换影响

即使页面开始跳转,已经加入事件循环的定时器任务仍然会执行,因为它与页面的显示状态无关。
异步任务一旦被添加到事件循环中,就会独立于页面状态继续执行,这是JavaScript的基本特性。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容