我的知识记录分享
云函数可以以函数的形式自动运行后端代码以响应API调用和HTTPS触发的事件,开发者只需关注业务代码本书,无需关心后端运维、计算资源等,平台会根据负载自动进行扩缩容。各个云函数相互独立,执行环境相互隔离。
云函数在操作上与以往的开发方式会有所不同,不过它依然还是JavaScript知识的应用。在这一章,我们会来讲解云函数如何新建、如何部署、如何调用,在操作上我们需要注意哪些细节等。
使用开发者工具,鼠标右键云函数根目录如cloudfunctions,在弹出的窗口选择新建Node.js云函数,然后输入云函数的名称比如sum
(可以先右键同步云函数列表,保证没有重名),按Enter确认后,微信开发者工具会在本地(你的电脑)创建出sum云函数目录,同时也会在线上环境中创建出对应的云函数(也就是自动部署好了,可以到云开发控制台云函数列表里看到)。
cloudfunctions //云函数根目录 ├── sum // 云函数目录 │ └── index.js
│ └── config.json
│ └── package.json //云函数的Node包管理 miniprogram //小程序根目录 ├── ...
打开sum云函数目录下的index.js并将里面的代码修改为如下,然后右键index.js文件,选择云函数增量上传:(更新文件),这样一个用来求两个参数之和的云函数就更新好了:
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV,
})
exports.main = async (event, context) => { const sum = event.a + event.b return sum
}
这里的event
对象指的是触发云函数的事件,在小程序端调用时,event
是小程序端调用云函数时传入的参数对象,也就是说要计算sum
,我们需要在小程序端调用云函数时传入两个参数a
和b
。
结合前面的知识,要调用云函数有很多种方式,比如我们可以在调试器的console控制台调用接口、在生命周期函数里调用,还可以通过组件绑定一个事件处理函数来调用等等,这些方式都是大同小异,都是在调用wx.cloud.callFunction()
接口。
打开调试器的console控制台,我们可以输入以下代码然后执行,name是要调用的云函数名称,而data则是要传递给云函数的参数:
res =>
在控制台,我们可以看到如下打印的结果,首先它会返回这是一个Promise,然后调用完成之后再返回调用的结果,也就是res对象:
{ errMsg: "cloud.callFunction:ok", result: 38, requestID: "afa3e19a-e389-11ea-ad2f-5254007c2bc0" }
result才是云函数返回的结果,errMsg是云函数执行是否成功,而requestID是云函数执行 ID,可用于日志查询。我们可以将云函数的调用函数放到生命周期函数或者事件处理函数里,再通过this.setData
赋值给用于数据绑定的Page()里的data对象,最后就可以渲染出来了,我们来看下面的案例。
使用开发者工具将sum云函数的代码修改为如下,我们让云函数返回更多类型的数据,修改完之后,右键index.js文件,选择云函数增量上传:(更新文件):
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV,
})
exports.main = async (event, context) => { let lesson = "云开发技术训练营"; let enname = "CloudBase Camp"; let x = 3, y = 4, z = 5.001, a = -3, b = -4, c = -5; let now = new Date(); return {
movie: { name: "霸王别姬", img: "https://img3.doubanio.com/view/photo/s_ratio_poster/public/p1910813120.webp", desc: "风华绝代。" },
movielist:["肖申克的救赎", "霸王别姬", "这个杀手不太冷", "阿甘正传", "美丽人生"],
charat: lesson.charAt(4),
concat: enname.concat(lesson),
uppercase: enname.toUpperCase(),
abs: Math.abs(b),
pow: Math.pow(x, y),
sign: Math.sign(a),
now: now.toString(),
fullyear: now.getFullYear(),
date: now.getDate(),
day: now.getDay(),
hours: now.getHours(),
minutes: now.getMinutes(),
seconds: now.getSeconds(),
time: now.getTime()
}
}
index.js增量上传更新到云开发环境之后,我们可以在一个小程序页面比如新建一个function页面,然后在function.js的生命周期函数onLoad里调用这个云函数并将获取的数据赋值给data:
function (options)
使用开发者再在function.wxml里输入以下代码,这里用的就是我们前面学过的页面渲染的知识,编译之后数据就在小程序端渲染出来了:
<view>"云开发技术训练营"第5个字符 {{result.charat}}</view> <view>两个字符串连接后的结果:{{result.concat}}</view> <view>CloudBase Camp字母大写:{{result.uppercase}}</view> <view>b的绝对值:{{result.abs}}</view> <view>x的y次幂:{{result.pow}}</view> <view>返回a是正还是负:{{result.sign}}</view> <view>now对象:{{result.now}}</view> <view>{{result.fullyear}}年</view> <view>{{result.date}}日</view> <view>星期{{result.day}}</view> <view>{{result.hours}}时</view> <view>{{result.minutes}}分</view> <view>{{result.seconds}}秒</view> <view>1970年1月1日至今的毫秒数:{{result.time}}</view>
从以上的案例可以看到,小程序端渲染的数据来源于云函数,而且云函数支持各类数据类型,不仅如此云函数还可以调用数据库返回给小程序端,这也是后端服务的基础。
值得注意的是,云函数返回的时间和小程序端返回的时间(北京时间)是不一样的,这是因为云函数中的时区为 UTC+0,不是 UTC+8,格式化得到的时间和在国内的时间是有8个小时的时间差,但是时区不会影响时间戳,所以尽量不要在云函数端将时间字符串化。
wx-server-sdk是微信小程序服务器端的SDK,SDK包括用于微信免鉴权的私有协议、云数据库、云存储、云调用等基础能力,因此每一个云函数都会使用到wx-server-sdk这个Node包。由于每个云函数实例之间是相互隔离的(没有公用的内存或硬盘空间),所以每个云函数都要求单独安装wx-server-sdk,Node包在云函数实例之间不存在复用的关系。而要调用这个包都需要安装好Node.js环境才能在本地电脑的开发者工具进行本地调试。
给云函数安装依赖时,在开发者工具上右键云函数目录如sum,选择开发者工具自带的终端(更建议)或外部终端窗口,直接输入npm install
即可。npm包管理器自动会安装好package.json的dependencies写好的包,建议将wx-server-sdk的版本号换成latest。
"dependencies": { "wx-server-sdk": "latest" }
sum安装好node依赖之后,就会在云函数目录里有一个node_modules的文件夹。当我们要将本地的云函数部署到云开发环境时,可以右键云函数目录选择上传并部署所有文件(更建议)或上传并部署:云端安装依赖(不上传node_modules)。
如果云函数本地没有安装依赖,就没法在开发者工具对云函数进行本地调试,部署上传云函数时,选择上传并部署所有文件就会报错,截图如下:
wx-server-sdk只是云函数必备的一个依赖,云函数还可以通过package.json安装更多功能丰富的Node包,这些我们会在教程的【用云函数实现后端能力】详细介绍。当在package.json里新增了其他依赖时,都需要使用
npm install
进行依赖的下载。
在云函数中调用其他API前,同小程序端一样,也需要执行一次初始化方法,首先使用require引入wx-server-sdk依赖,然后在初始化cloud.init()
中指定云开发的环境,方法如下:
//方法一,直接使用字符串envId指定环境 const cloud = require('wx-server-sdk')
cloud.init({ env: 'xly-xrlur' //换成你的云函数envId }) //方法二,使用cloud.DYNAMIC_CURRENT_ENV常量,也就是使用云函数当前所在环境 const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV //注意它不是字符串,不要加引号 })
cloud.init()
不指定环境在某些特定情况下仍然可以使用,比如你的云函数就部署在你创建的第一个云开发环境里,但是非常不推荐这种写法;
cloud.DYNAMIC_CURRENT_ENV
标志的是云函数当前所在的环境,也就是你将云函数部署到哪个环境,它就是指哪个环境;
env:{"database":"xly-xrlur","storage":"xly-1o7da","functions":"xly-oau0j"}
;
找不到对应的FunctionName
,可能是你的小程序账号之下有多个云开发环境,而你在云函数初始化时没有指定envId。
当我们右键云函数根目录cloudfunctions时,会有一个同步云函数列表的选项,它可以拉取当前云开发环境所有云函数的列表,右键指定的云函数选择下载就可以将云端的代码给下载到本地电脑。也就是说,上传到云开发环境的云函数以及代码都会存储在云端,你可以在其他设备上通过这种方式进行同步,除非你在云开发控制台将这个云函数给删掉了。
当我们在开发者工具本地或使用云开发控制台将云函数删掉之后,建议先同步云函数列表,不然在重新上传部署同名的云函数的时会出现一些报错。
在前面我们也已经介绍过右键云函数根目录cloudfunctions,选择新建Node.js云函数可以直接在云端新建一个云函数,同时会自动在云端给新建的云函数安装好wx-server-sdk依赖,并将该云函数在云端部署的情况反馈到开发者工具,即开发者工具本地的云函数目录图标会变色(注意区分同步和没有同步的云函数目录图标的不同)。
弄明白了这个机制以及前面的上传并部署所有文件、上传并部署:云端安装依赖(不上传node_modules),你才能理清什么时候需要我们在本地下载依赖,什么时候只需要更新代码本身就可以。
如果你在云端已经部署好了一个云函数所需要的依赖,那在编写云函数的核心文件index.js、权限配置文件或云函数其他目录文件时就不需要再上传并部署所有文件或上传并部署:云端安装依赖(不上传node_modules),只需要右键云函数目录,选择云函数增量上传:更新文件,这种方式只更新我们修改过的文件,更快捷。
发表评论: