评论

总结的一些血与泪的教训

昨天开发的小程序,因为一些很简单的问题卡了很久,总结了一些血与泪的教训,分享给大家,虽然可能大家都已经知道了

云函数

  • 云函数的上传流程

    云函数必须先保存后上传,因为编译器不会在上传的时候自动保存。

    保存的方法可以是CTRL+S或者是编译都可以,CTRL+SHIFT+S和编译是等效的;上传的方式可以是对文件的增量更新或者说部署云函数。主要是顺序必须先保存后上传。

    云函数部署对于触发器并没有效果,触发器得单独上传(仍然需要先编译)。

  • 如何知道云函数是否执行出错了

    云开发→云函数→日志,读取日志,可以读取服务器返回的数据,所以云函数中最好用try{}catch(e){}结构,然后return JSON.stringify(e),当然你不这样也没问题,因为服务器会自动吧错误写进日志

    云函数中console.log()的内容会写在日志的末尾。

    当然,你也可以使用云函数的本地调试功能(来自Littlesnail大佬的分享),但是本地环境是缺少wx-server-sdk这个包的,需要自己用npm装,大家可以自行衡量。

  • 如何知道云函数是否真正执行完了

    之前一直在python平台的我根本没接触过node.js这种异步事件驱动的语言,被异步快整疯了

    首先说结论,你得把所有返回Promise类型的方法都加上await关键字,并函数变为async类型。

    所谓的Promise类型是指的一个虚的对象,他传递给某些函数后,对那些函数进行一个“保证”,保证过会会给那些函数数据。因此那些函数会先等着,等Promise返回数据后,提醒这些函数开始工作了,然后上一个工作完提醒下一个直到函数执行完。因为有些操作,比如数据库的读取是需要时间的,所以要是一直等着会阻塞整个线程。(node.js似乎是单线程的,这算是一直对多线程的补偿方案吧)

    Promise对象有三种状态。Pending,表示正在运行中;fulfilled,表示完成然后会自动提醒下一个函数;rejected,表示失败,当然如果你用try catch了就没事。

    重点来了,对于async的云函数来说,执行到最后或者return就相当于结束了,然而这个时候如果函数内仍然有处于“保证中”(Pending)的Promise对象,云函数是不会等它执行完才返回的,它会直接返回。所以你必须加一个关键字,await,表示下面的语句都会等着这个异步操作完成再工作,也就是阻塞住。这样才能真正使得云函数完全执行完。

    如何判断什么函数返回的是Promise对象,在开发者工具的console里面输入一下这个函数就行了,实在不行typeof。

    PS:以前我曾经想过,如果吧云函数的async标签去掉,是否能实现不需要await也能正常运行呢,答案是,你想的美,去掉后人家该Promise还是Promise,不会给你变成现实(特朗普:恶意的zz隐喻,举报了)。所谓的async标签是指的我警告你我这玩意是异步的,你能用then,但是大多数情况你都不会去用then,所以,老老实实await吧。

你们就不要挣扎了,老老实实吧所有出现异步的位置都async和await吧

你标了async的函数,调用它的函数也得加async哦,而且调用的时候也得await

【async-await地狱】

  • 小细节

    云函数的运行环境中你不能获取到函数的信息,this.name,this.toString(),或者window.decodePathName都是undefine

数据库

  • 为什么有时候数据库的get没用

请确定你的权限是否有误,在 云开发控制台-数据库-权限设置 中可以调整,一般来说选第一个权限

  • 为什么有时候数据库的update没用

    首先当然是排查是不是因为在云函数中你却没有加await,数据库的几乎所有操作全是异步的,返回的基本都是Promise对象,另一点是小程序中的db.collection('seats')对象是动态对象,你不能这样写

db_seats=db.collection('seats')
db_seats.where({})

    如果你在下面的语句继续用db_seats来直接对数据库做一些操作,相当于你创建了一个数据库的本地副本,你get()数据当然是有用的,但是可能不是最新的数据,但是你add()和update()都是没用的。你必须每次都用db.collection('xxx')来调用xxx数据库。

    (实际上后来经过调查发现,add有时候是可以的,但是update保证每次都不行,不知道为啥)

————(以下为更新内容)————

事实上还有一种更加广泛的错误

一定要注意,doc函数查到的是数据库的索引的_id字段,而不是_openid字段,你拿openiddoc一定找不到东西。

所以如果你一开始只有openid这个数据,那你最好先用where找到对应数据的_id,然后再doc它的id

(为什么不直接where后接update?where返回的是一个数组,where接update相当于一次性修改一组数据,只有服务器端,也就是云函数有这个权限,小程序的前端只能先查询再修改)

  • 数据库传入的数据

    只有数据库的where(),update(),add(),传入的JSON数据中,只有data是必选属性,其他属性像是successfail都是非必要的,如果你不用错误处理的话就不用加

  • then怎么用

    数据库的then(),或者说所有的异步操作的then,你把函数放在then()里面表示到时间后完成某项操作,比如

//获取所有data
const seats_list = await db.collection('seats').where({
    used: true
  })
  .get().then(res => {
    // return res.data
    console.log(res.data)
  })

    

相当于吧收到的参数命名为res,然后等res异步返回后,会在=>{}里面处理一些只跟res有关的操作,这当然是有用的,但是问题在于then里面是一个闭包,你console.log当然是可以的,但是你要在里面用this.setData()就不行了,这个闭包的this可不是指的你这个外面的对象,他就是指的它点前面的对象,也就是get()后返回的对象。

    所以想在外面用的话,正确操作是吧注释去掉,也就是return res或者return res.data,然后这样的话,外面的seats_list 就能被赋值为res或者res.data了,然后接下来的语句尽情对seats_list 操作,千万别忘了加await,否则你懂的。

WXML

  • 为啥我的wx:if不管用

        请注意一件事,那就是。。。WXML里面的任何函数部分,都是不能有空格的,比如这样写

点击选座位

点击选座位
点击选座位
点击选座位
点击选座位


        无论你空格加在哪里,只要被""括起来,加空格都会使得wx:if失效,相信小伙伴们此时已经反应过来了,没错,这就是JS那个傻逼机制,非空字符串相当于true

> Boolean(" ")
> true


    我猜wx:if的机制只是简单的做了下拆分,然后配对了下,并不能实际把它当程序运行(甚至可能正则都没用),所以如果遇到了它没拆成功的字符串,它就干脆暴力返回原字符串,当然被识别为true了。

整体

  • Js的所有变量都需要预先var
  • 数据库的Data和云函数的Data

    JS的Date()函数很迷,它返回的是tm一个String,当前时间的String,你必须用var new才能构造一个真正的Date对象而不是一个字符串,也就是按照下面方法使用,加注释的都是错误的用法。

var nowdate=new Date()
// Date().getDate()
// Date(一个Date对象).getDate()
// Date(一个字符串).getDate()

    另外就是无论你在哪调用这个函数,他创建的都是你调用端的时间,而不是云端的时间,就算你在云函数调用也一样,你电脑或者手机是几点他创建的就是几点,我都服了。

    云端的时间只能用db.serverDate()来构建,但是问题在于db.serverDate()是tmd一个指令,他返回的不是一个Date,而是类似db.commend那种类型的东西,给传入服务器的data用。

//更新nowdate为服务器时间
await db.collection('seats').where().update({
  data:{
    nowdate:db.serverDate()
  }

    也就是你平时用是没JB用的,你只能老老实实去用JS的Date方法请求世界时然后倒时区。

总结

  • 以后想到了继续补充,欢迎大佬分享
最后一次编辑于  2020-05-11  
点赞 12
收藏
评论

8 个评论

  • 总有刁民想害朕
    总有刁民想害朕
    2020-10-21

    大佬,前端童鞋寻求帮助,在小程序api云开发,根据openid字段查找表,如果查到表有这个字段值就更新,否则就增加一条数据,这个怎么写?

    2020-10-21
    赞同
    回复 1
    • _Me
      _Me
      2022-03-14
      欸,我昨晚才写了这么一个功能
      2022-03-14
      回复
  • 小肥羊🍊
    小肥羊🍊
    2020-05-15

    来自Littlesnail大佬的分享

    分享的什么?可以分享下吗

    2020-05-15
    赞同
    回复
  • 人在江湖
    人在江湖
    2020-03-07

    补充一下,update 操作不成功,有可能是数据库的记录中没有 _openid 字段,也就是说通过控制台创建的数据,是无法修改的,只能通过云函数实现。

    2020-03-07
    赞同
    回复
  • 人在江湖
    人在江湖
    2020-03-07

    总结的真好,学习了

    2020-03-07
    赞同
    回复
  • 郑旭东
    郑旭东
    2019-10-13

    云函数里new Date是客户端时间?我被震惊了

    2019-10-13
    赞同
    回复
  • Littlesnail
    Littlesnail
    2019-10-12

    你的电脑上先安装好nodejs的运行环境,然后再通过npm安装微信小程序的wx-server-sdk包就可以勾选本地调试了。。

    2019-10-12
    赞同
    回复 1
    • 2019-10-12
      谢大佬,补充到文章了
      2019-10-12
      回复
  • Littlesnail
    Littlesnail
    2019-10-12

    云函数有个本地调试功能,可以调试

    2019-10-12
    赞同
    回复 3
    • 2019-10-12
      之前用本地调试的时候好像报错了,缺wx-server-sdk这个包
      2019-10-12
      回复
    • Littlesnail
      Littlesnail
      2019-10-12回复
      你的电脑上先安装好nodejs的运行环境,然后再通过npm安装微信小程序的wx-server-sdk包就可以勾选本地调试了。。
      2019-10-12
      回复
    • Littlesnail
      Littlesnail
      2019-10-12回复
      本地调试
      2019-10-12
      回复
  • bibolibo
    bibolibo
    2019-10-12

    谢,大佬留经验


    2019-10-12
    赞同
    回复 3
    • 2019-10-12
      别别,我是前天刚开始写小程序的,超级大萌新
      2019-10-12
      回复
    • bibolibo
      bibolibo
      2019-10-12回复
      都是萌新啦,互相帮助...
      2019-10-12
      回复
    • Littlesnail
      Littlesnail
      2019-10-12
      你的电脑上先安装好nodejs的运行环境,然后再通过npm安装微信小程序的wx-server-sdk包就可以勾选本地调试了。。
      2019-10-12
      回复
登录 后发表内容