总结的一些血与泪的教训
云函数 云函数的上传流程 云函数必须先保存后上传,因为编译器不会在上传的时候自动保存。 保存的方法可以是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字段,你拿openid去doc一定找不到东西。 所以如果你一开始只有openid这个数据,那你最好先用where找到对应数据的_id,然后再doc它的id (为什么不直接where后接update?where返回的是一个数组,where接update相当于一次性修改一组数据,只有服务器端,也就是云函数有这个权限,小程序的前端只能先查询再修改) 数据库传入的数据 只有数据库的where(),update(),add(),传入的JSON数据中,只有data是必选属性,其他属性像是success,fail都是非必要的,如果你不用错误处理的话就不用加 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方法请求世界时然后倒时区。 总结 以后想到了继续补充,欢迎大佬分享