uniCloud开发云函数
简介
云函数是运行在云端的JavaScript
代码,和普通的Node.js
开发一样,熟悉Node.js
的开发者可以直接上手。
如下是将传入的两个参数求和并返回客户端的云函数代码示例:
'use strict';
exports.main = async (event, context) => {
//event为客户端上传的参数
return {
sum:event.a + event.b
}
}
云函数的传入参数有两个,一个是event
对象,一个是context
对象。event
指的是触发云函数的事件,当客户端调用云函数时,event
就是客户端调用云函数时传入的参数。context
对象包含了此处调用的调用信息和运行状态,可以用它来了解服务运行的情况。uniCloud
会自动将客户端的操作系统(os
)、运行平台(platform
)、应用信息(appid
)等注入context
中,开发者可通过context
获取每次调用的上下文,如下是一个示例:
'use strict';
exports.main = async (event, context) => {
//event为客户端上传的参数
...
//context中可获取客户端调用的上下文
let os = context.OS //客户端操作系统,返回值:android、ios 等
let platform = context.PLATFORM //运行平台,返回值为 mp-weixin、app-plus等
let appid = context.APPID // manifest.json中配置的appid
let clientIP = context.CLIENTIP // 客户端ip信息
let clientUA = context.CLIENTUA // 客户端user-agent
... //其它业务代码
}
关于CLIENTIP、CLIENTUA
通过管理端调用云函数(云函数上传并运行、腾讯云开发调试期间),使用腾讯云时想临时调试UA、IP等可以通过自行初始化uniCloud
的方式(同时连多服务空间)传入debugFunction: false
来实现客户端直连调用,需要注意的是此时控制台将不会打印云函数日志。
云函数中如果要使用其他服务(比如MySQL数据库、Redis等),可以按照Node.js
的写法即可。
注意事项
服务商为阿里云时,暂不可使用相对路径读取文件(比如fs.readFileSync('./info.txt')
),可以使用绝对路径fs.readFileSync(path.resolve(__dirname,'./info.txt'))
访问数据库
云函数中支持访问本服务空间下的数据库,调用方式详见规范
访问HTTP服务
uniCloud
提供了uniCloud.httpclient
供开发者使用。无需额外依赖,就可以请求任何HTTP
和HTTPS
协议的 Web 服务。uniCloud.httpclient
返回的是一个urllib实例。
uniCloud.httpclient.request(URL, requestOptions)
requestOptions
参数说明:https://uniapp.dcloud.io/uniCloud/cf-functions
示例代码
const res = await uniCloud.httpclient.request(apiUrl, {
method: 'POST',
data: {
test: 'testValue'
},
dataType: 'json'
})
console.log(res)
使用npm
在云函数中我们可以引入第三方依赖来帮助我们更快的开发。云函数的运行环境是Node.js
,因此我们可以使用npm
安装第三方依赖。
注意:鉴于阿里云的限制,目前仅支持全量上传云函数(整个
node_modules
文件夹全部上传),因此尽量精简依赖,否则可能会每次上传时间很慢,影响开发体验注意:目前每个云函数上传包大小限制为
10M
客户端调用云函数
前端代码(H5前端、App、小程序),不再执行uni.request
联网,而是通过uniCloud.callFunction
调用云函数,callFunction
定义如下:
请求参数
字段 | 类型 | 必填 | 说明 |
---|---|---|---|
name |
String |
是 | 云函数名称 |
data |
Object |
否 | 客户端需要传递的参数 |
响应参数
字段 | 类型 | 说明 |
---|---|---|
result |
Object |
云函数执行结果 |
requestId |
String |
请求序列号,用于错误排查 |
示例代码
// promise方式
uniCloud.callFunction({
name: 'test',
data: { a: 1 }
})
.then(res => {});
// callback方式
uniCloud.callFunction({
name: 'test',
data: { a: 1 },
success(){},
fail(){},
complete(){}
});
云函数中调用云函数
用法同客户端调用云函数,不支持callback
形式
请求参数
字段 | 类型 | 必填 | 说明 |
---|---|---|---|
name |
String |
是 | 云函数名称 |
data |
Object |
否 | 云函数参数 |
响应参数
字段 | 类型 | 必填 | 说明 |
---|---|---|---|
errCode |
String |
否 | 状态码,操作成功则不返回 |
errMsg |
String |
否 | 错误描述 |
result |
Object |
否 | 云函数执行结果 |
requestId |
String |
否 | 请求序列号,用于错误排查 |
示例代码
let callFunctionResult = await uniCloud.callFunction({
name: "test",
data: { a: 1 }
})
注意事项
云函数的启动模式(冷启动、热启动)
基于云函数按需执行的特点,函数在不被触发的时候,计算资源是不被激活的。当一个云函数初次被触发时,其完整过程如下:
- 实例化计算实例
- 加载函数代码
- 启动 node
- 执行代码
函数被调用时,执行这些完整步骤的过程一般称作冷启动,冷启动的耗时长于热启动,一般在一秒出头。
而如果函数实例和执行进程都被复用的情况下一般被定义为热启动,热启动没有性能问题。
如果一个云函数实例长时间没有被再次调用,则该计算实例会被回收;后续再次调用该云函数时,就会再次触发云函数的冷启动。
不同云厂商的函数实例回收时间,以及优化冷启动的建议,参考
因为存在冷热启动的差异,云函数中的全局变量就可能出现每次不一样的情况。
以如下代码为例,count
作为全局变量,当多次调用该云函数时,可能会出现变量累加的情况(实例未复用时,每次返回0,若实例被复用,则可能返回1、2、3等各种意外情况)
let count = 0;
module.exports = async (event) => {
return count++
//此示例为错误示例
//云函数实例未复用时,每次返回0
//若实例被复用,则可能返回1、2、3等各种意外情况
}
临时存储空间
云函数是运行在云端的代码,运行环境由云服务器弹性调配,这是和传统Node.js
应用很大的区别。
换言之,云函数每次执行的宿主环境(可简单理解为虚拟机或服务器硬件)可能相同,也可能不同,因此传统Node.js
开发中将部分信息存储本地硬盘或内存的方案就不再适合,建议通过云数据库或云存储的方案替代。
云函数中的异步行为
书写云函数时应注意async
、await
的使用,Node.js
有内置模块util
可以将符合error-first
形式callback
的函数转换为promise
形式,详情参考,比如以下示例:
const {
promisify
} = require('util')
let testCallback = {
value: 'testCallbackValue',
echo: function(num, callback) {
setTimeout(() => {
// 第一个参数为error,第二个为返回值
callback(null, `${this.value}:${num}`)
}, 2000)
}
}
exports.main = async function() {
// num=2,不传入callback参数,callback会自动作为回调函数处理
let val = await promisify(testCallback.echo).call(testCallback, 2)
console.log(val)
return val
}
如果想在云函数内使用回调形式可以让云函数返回一个promise
,如以下示例:
exports.main = async function() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('some return value')
}, 1000)
})
}
其它
- 云函数中使用的时区是
UTC+0
,而不是UTC+8
,在云函数中使用时间时需特别注意 - 使用阿里云作为服务商时,暂时无法使用相对路径读取文件,如:
fs.readFileSync('./info')
,可以替换为fs.readFileSync(path.resolve(__dirname,'./info'))
版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/03/18/develop-cloud-functions-using-unicloud/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。
共有 0 条评论