uni-app拍照功能,部分机型白屏导致图片丢失的问题(事件循环机制)

948 阅读2分钟

最近使用uni-app做了一个小程序的项目,有一个功能是把多个文件拍照并上传。

在使用过程中部分机型白屏会导致页面报错,图片丢失。我研究了一下,找到了解决办法。

下面我简化代码,展示一下此功能的过程

  • DOM
<template>
    <view>
        <image :src="item" alt="" v-for="item in imgList" :key="item.id">
    </view>
</template>
  • data里面定义图片列表imgList
data(){
    return{
        imgList:[]
    }
}
  • 调用上传的接口,参数与返回值简写了
upload(params).then(res=>{
    this.imgList.push(res)
})

代码很正常,但在部分机型下在拍完照片之后页面会白屏几秒,页面重新加载,导致控制台报错。错误是这样的

导致这种错误的原因是:在元素加载之前,JavaScript 中使用了 DOM 元素。而 DOM API 对于空白的对象引用返回 null。任何执行和处理 DOM 元素的 JS 代码,都应该在创建 DOM 元素之后执行。

现在我们知道了原因,就知道从哪里入手了。我们让DOM解析完成之后,再去执行js的操作,这就涉及到了事件循环。

首先,事件循环分为宏任务和微任务。

  • 初始化页面的时候,执行宏任务,即script 脚本(整体代码),执行过程中,遇到微任务放入微任务队列,遇到宏任务,放到宏任务队列。
  • script 脚本执行完成,开始执行微任务,清空微任务队列,然后执行宏任务,清空宏任务队列。之后开始进入下一次事件循环。

我们现在就清楚的知道,拍完照执行的js代码需要在script 脚本执行完成之后在执行,所以我们有两种方式可以解决。把代码放入微任务里执行或者放入宏任务里执行

这里我采用的是放入宏任务里执行。在原代码基础上加个setTimeout。

upload(params).then(res=>{
    setTimeout(()=>{
        this.imgList.push(res)
    })//不写时间,默认为0
})

知道原理之后,解决方法很简单。所以,重要的是分析产生问题的原因。

希望此文章能给到你帮助!