setTimeout在小程序中的问题及背后原因小程序逻辑层运行的原理

906 阅读2分钟

我正在参加跨端技术专题征文活动,详情查看:juejin.cn/post/710123…

最近在使用uniapp开发微信小程序中,需要增加一个首屏广告功能,三秒后跳转首页也可以点击跳过,本来一个很简单功能,使用setTimeout设置三秒后跳转,并且保存定时器编号,如果点跳过,则使用clearTimeout清除该定时器,但是却遇到一个bug,那就是在首次进入小程序后,点击跳过clearTimeout并不能够清理掉定时器编号,因此翻阅文档,发现我们需要在onHide,onUnload中进行清除,但是背后的原因驱使我重新阅读了一遍小程序文档,更深入了解其原理。

  • onLoad中setTimeout自动跳转
  data() {
      return {
            timer:'',
      }
    },
   async onLoad(option) {
            this.timer=setTimeout(()=>{
		uni.reLaunch({
			url:'/index'
		})
	},3000)
}
  • 点击跳转

点击跳转清除定时器并跳转至首页,但在初次进入时,清除定时器并不生效

handleToIndex(){
	 // if(this.timer!==''){
		//clearTimeout(this.timer);
	//}
	uni.reLaunch({
		url:'/index'
	})
}
  • 解决方案

onHide,onUnload中清除定时器

onHide() {
	clearTimeout(this.timer);
},
onUnload(){
        clearTimeout(this.timer);
},

那么造成这个bug的原因是什么呢,可以从小程序的线程即逻辑层服务及其页面生命周期来研究, 小程序在运行环境中分为逻辑层与渲染层, WXML 模板和 WXSS 样式工作在渲染层,JS 脚本工作在逻辑层。 小程序的渲染层和逻辑层分别由2个线程管理, AppService负责逻辑层的运行,使用 JavaScript 引擎为小程序提供开发者 JavaScript 代码的运行环境以及微信小程序的特有功能,所有代码最终将会打包成一份 JavaScript 文件,并在小程序启动的时候运行,直到小程序销毁。

  • 小程序的渲染层及逻辑层 4-1.ad156d1c.png

  • 小程序页面生命周期

小程序以栈的形式维护页面,随着路由的切换,页面不断进栈出栈,触发生命周期。 page-lifecycle.2e646c86.png 当我们切换路由,页面发生切换时,小程序会回收部分页面,从而造成使用方法的形式进行定时器编号清除会失败。因此我们需要在页面的生命周期中进行定时器编号的清除。 1655450453673.jpg 在生命周期中清除定时器,我们要根据页面会触发的生命周期进行选择,最后选择为onUnload: 监听页面卸载,onHide:当小程序从前台进入后台

  • 小程序页面切换会触发的生命周期 1655452301671.jpg