评论

总结的一些血与泪的教训

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

云函数

  • 云函数的上传流程

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

    保存的方法可以是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

数据库

  • 为什么有时候数据库的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保证每次都不行,不知道为啥

  • 数据库传入的数据

    只有数据库的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里面的任何函数部分,都是不能有空格的,比如这样写

<!-- 正确写法 -->
<button wx:if="{{user_data.state=='online'}}" bindtap="tap_choose_seat">点击选座位</button>
<!-- 以下写法都是错的 -->
<button wx:if="{{user_data.state=='online '}}" bindtap="tap_choose_seat">点击选座位</button>
<button wx:if=" {{user_data.state=='online '}}" bindtap="tap_choose_seat">点击选座位</button>
<button wx:if="{{user_data.state =='online'}}" bindtap="tap_choose_seat">点击选座位</button>
<button wx:if="{{ user_data.state=='online'}}" bindtap="tap_choose_seat">点击选座位</button>

        无论你空格加在哪里,只要被""括起来,加空格都会使得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方法请求世界时然后倒时区。

总结

  • 以后想到了继续补充,欢迎大佬分享

最后一次编辑于  10-13  
点赞 4
收藏
评论

4 个评论

  • 郑旭东
    郑旭东
    10-13

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

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

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

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

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

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

    谢,大佬留经验


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