个人技术博客——微信小程序Collection.watch()应用总结

222000433罗彤 学生 2023-06-07 00:15:55
这个作业属于哪个课程2023年福大-软件工程实践-W班
这个作业要求在哪里软件工程实践总结&个人技术博客
这个作业的目标总结心得、回顾并思考过去提出的问题、自我评估、完成个人技术博客
其他参考文献相关链接置于文末

目录

  • 一、技术概述
  • 1.1 使用场景
  • 1.2 学习该技术的原因
  • 1.3 技术难点
  • 二、技术详述
  • 2.1 方法描述
  • 三、遇到的问题及解决过程
  • 3.1 监听器查询语句正确,但无法监听到数据库变化
  • 3.2 想要根据数据库不同的变化触发不同的事件
  • 3.3 按照开发文档给出的编写方法,无法正确关闭监听器
  • 四、总结
  • 五、参考链接

一、技术概述

1.1 使用场景

在小程序中实现聊天功能,或者是在游戏中与队友的游戏数据保持一致,等等这些都是通过数据实时推送进行的。因此需要实时监听集合中的数据条数。

1.2 学习该技术的原因

专业的的聊天IM整合和改造难度较大,免费版本使用受限较多,监听数据库集合是简便省力的平替方法,代码可维护性强。
Collection.watch方法类似于vue的watch方法,学习成本低。

1.3 技术难点

有时候要对具有相同查询条件的不同字段的不同变化执行不同的回调函数,而相同的监听器只允许存在一个(监听器一般声明类型为const,并且需要在onUnload周期函数中关闭监听器,监听器重名会导致一系列问题),因此如何将不同动作编写在同一个回调函数中是一个难点。

二、技术详述

2.1 方法描述

Collection.watch(options: Object): Object

  • 必填参数:成功回调函数onChange(snapshot)、失败回调函数onError(),其中snapshot为变更快照。
  • 返回值:watcher对象,具有一个close()方法用来关闭监听
  • snapshot结构
    docChanges:ChangeEvent数组,表示更新事件数组
    docs:object数组,代表数据快照,表示此更新事件发生后查询语句对应的查询结果
    type:string,代表快照类型,仅在第一次初始化数据时有值,为init
    id:number,代表变更事件的id
  • ChangeEvent说明
    注:此处仅摘出常用的几个字段进行说明,完整版可见于文末微信开放文档路径。
    dataType:string,表示记录的具体更新类型,枚举值,定义见DataType
    updatedFields:object,所有更新的字段及字段更新后的值,key为更新的字段路径,value为字段更新后的值(仅在update操作时有此信息)
  • DataType 枚举值
    init:表示初始化监听数据
    update:表示符合查询的记录内容更新,对应 update操作
    replace:表示符合查询的记录内容被替换,对应数据库set操作
    add:表示符合查询的记录新增,对应add操作
    remove:表示符合查询的记录被删除,对应数据库remove操作
  • 使用示例:
    const db = wx.cloud.database()
    const watcher = db.collection('todos')
    // 按 progress 降序
    .orderBy('progress', 'desc')
    // 取按 orderBy 排序之后的前 10 个
    .limit(10)
    // 筛选语句
    .where({
      // 填入当前用户 openid,或如果使用了安全规则,则 {openid} 即代表当前用户 openid
      _openid: '{openid}'
    })
    // 发起监听
    .watch({
      onChange: function(snapshot) {
        console.log('docs\'s changed events', snapshot.docChanges)
        console.log('query result snapshot after the event', snapshot.docs)
        console.log('is init data', snapshot.type === 'init')
      },
      onError: function(err) {
        console.error('the watch closed because of error', err)
      }
    })
    

三、遇到的问题及解决过程

3.1 监听器查询语句正确,但无法监听到数据库变化

  • 在确保查询语句正确无误后仍无法正确触发监听器,需要检查数据库权限设置,需要给数据库设置用户可读的权限;另外,云开发请求次数超过订阅套餐的上限后,该方法有1/10的概率失灵,重启调试后可恢复正常。
  • 还有一种可能,请求查询的条件是当前Page的data变量,它通过请求云函数获得。由于请求云函数是双线程的,因此需要通过.then()方法进行链式调用,确保代码顺序执行,得到有效的查询条件。

3.2 想要根据数据库不同的变化触发不同的事件

编写合适的条件判断语句来区分要执行的代码。为举例方便,假设有一集合的记录内容类型均如下:

{
name:'张三',
age:18,
school:'FZU'
}

1. 确定更新事件的类型
使用snapshot.docChanges[0].dataType==DataType枚举值来确定本次监听到的事件类型,如只需要在初始化时执行的代码,则可以写snapshot.docChanges[0].dataType=="init" ,docChanges[0].dataType一般不会为undefined,不需要额外判断。

2. 确定被更新的字段

  1. 当监听的记录同时只改变一个字段时:
    docChanges[0].updatedFields的返回值为一个键值对 (改变的字段名,改变后的值) 。
    使用Object.keys(snapshot.docChanges[0].updatedFields)=='age' 判断改变的字段是否为age。其中Object.keys用于得到返回键值对的键(上例中为age)。

  2. 当监听的记录同时会改变多个字段时:
    docChanges[0].updatedFields的返回值为一个键值对数组。
    使用in运算符判断这多个字段的键是否在返回数组中。如if('name'&&'school' in snapshot.docChanges[0].updatedFields),用来判断监听到变化的字段是否为name和school。

3. 示例:

//onLoad中
watcher=db.collection('user_record')
        .where({
          status:true,
          game_record_id:this.data.game_record_id
        })
        .watch({
          onChange:(snapshot)=>{
            console.log('watcher3 snapshot',snapshot);
            //当监听到更新的字段为isReady时
            if(snapshot.docChanges[0].dataType=="update"&&Object.keys(snapshot.docChanges[0].updatedFields)=='isReady'){
                // 直接修改当前Page的data变量
              this.setData({
                players2:snapshot.docs
              })
              console.log('players2:',this.data.players2);
            }   
            //当更新的字段中包含status时 
            if (snapshot.docChanges[0].dataType=="update"&& 'status' in snapshot.docChanges[0].updatedFields){
                //调用业务函数
              wx.cloud.callFunction({
                name:'getUserList',
                data:{
                  game_record_id:this.data.game_record_id
                }
              })
            //   用快照数组修改当前Page的data变量
              this.setData({
                players2:snapshot.docs
              })
            }     
          },
          onError:(e)=>{
            console.log('error',e);
          }
        })

// onUnload中
watcher.close();

3.3 按照开发文档给出的编写方法,无法正确关闭监听器

监听器一般放在onLoad中实现,所以应将监听器声明为当前页面的全局常量,这样才能在onUnload中正常关闭监听器。

四、总结

使用 watch 时,支持 where, orderBy, limit,不支持 field。
调式基础库需要在2.9.2版本以上。

五、参考链接

微信开放文档-Colletion.watch

...全文
265 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

688

社区成员

发帖
与我相关
我的任务
社区描述
2023年福州大学软件工程实践课程W班的教学社区
软件工程团队开发软件构建 高校 福建省·福州市
社区管理员
  • FZU_SE_teacherW
  • 张书旖
  • 郭渊伟
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧