uniCloud - 云函数 的基本使用

发布时间:2024年01月14日

目录

基本概念

简介

?快速上手

1.新建云函数

2.使用云函数

callFunction方法

云函数的入参

获取云函数调用来源

云函数的返回格式

uniCloud响应体规范

总结案例

新建云函数

使用云函数?

展示?


基本概念

云函数即在云端(服务器端)运行的函数。

从 HBuilderX 3.4起,新增了云函数的扩展版,云对象。

开发者无需购买、搭建服务器,只需编写代码并部署到云端即可在客户端(App/Web/小程序等)调用,同时云函数之间也可互相调用。

一个云函数的写法与一个在本地定义的?JavaScript?方法无异,代码运行在云端?Node.js?中。当云函数被客户端调用时,定义的代码会被放在?Node.js?运行环境中执行。

开发者可以如在?Node.js?环境中使用?JavaScript?一样在云函数中进行网络请求等操作,也可以使用 node_modules。

但 DCloud提供了 uniCloud对象 内置在云函数/云对象中,开发者使用更多的是 uniCloud 的 api,不了解 node 不影响开发。

HBuilderX 3.0起版本,在uniCloud/cloudfunctions目录右键创建云函数,如下:

在HBuilderX 3.4起,上述界面更新为 新建云函数/云对象。

云对象本质是对云函数的一种封装,可以对象化的方式使用云服务。

HBuilderX 3.0之前版本,项目下没有uniCloud目录,直接在cloudfunctions目录上右键、新建云函数

云函数修改后,可以本地运行。只有上传到云端,方可在云端生效。

更多云函数介绍参考规范

?

简介

云函数是运行在云端的?JavaScript?代码,是基于?Node.js?的扩展。

在常规的?Node API?基础上,uniCloud的云函数环境内置了uniCloud对象,这个对象内置了网络、数据库等各种API。开发者未学习过?Node.js?也没有关系,只需要看uniCloud的文档,掌握这个uniCloud对象的API即可。

每个云函数是一个js包,在云函数被调用时,由 serverless 调度系统分配硬件资源启动一个 node 环境来运行这个云函数。

在HBuilderX中可以新建云函数(HBuilderX 3.4 同时可以新建云对象)。?


每个云函数是一个目录,其中普通云函数有index.js入口文件,云对象的入口文件则是index.obj.js

一个最简单的云函数只需要这个入口js文件,在里面编写代码即可。当然也可以在这个js中require该云函数目录下的其他js、json文件。

云函数的配置文件和 npm规范 相同,在云函数目录下可新建一个 package.json 来存放配置。uniCloud云函数扩展了 package.json,增加了一些特有的配置项。详见

云函数启动后实例会保留一段时间(如15分钟),超过保留期后若该云函数一直没有被再调用,那这个实例会被释放。所以云函数有冷启动的概念。不过由于js实例的启动要比php和java更快,所以js更适合serverless方式。

注意事项

  • 云函数内使用commonjs规范,不可使用import、export,参考:commonjs模块
  • 不同项目使用同一个服务空间时,不可使用同名云函数。同名云函数会相互覆盖。
  • 在HBuilderX创建云函数时,如果新云函数与服务器上已存在同名云函数,会用新函数覆盖。所以应先选择从服务空间下载云函数。
  • 单个云函数大小限制为10M(包含node_modules),过大的云函数影响运行性能,也会增加计费的gbs。同时支付宝小程序云与腾讯云支持在云端安装node_modules,此时不占用云函数体积。
  • uniCloud的阿里云版与支付宝小程序云版,暂不可使用相对路径读取文件(比如fs.readFileSync('./info.txt')),可以使用绝对路径fs.readFileSync(path.resolve(__dirname,'./info.txt'))

?快速上手

?云函数是运行在云端的 JavaScript 代码,是基于 Node.js 的扩展

? ? ? ? 在常规的 Node API 基础上,uniCloud 的云函数环境内置了 uniCloud 对象,这个对象内置了网络、数据库等各种API。开发者未学习过 Node.js 也没有关系,只需要看 uniCloud 的文档,掌握这个 uniCloud 对象的API即可。

? ? ? ? 每个云函数是一个js包,在云函数被调用时,由 serverless 调度系统分配硬件资源启动一个 node 环境来运行这个云函数。
? ? ? ? 操作数据库?

1.新建云函数

云函数目录下 - 新建云函数/云对象

?

2.使用云函数

callFunction方式云函数,也称之为普通云函数。

uni-app的前端代码,不再执行uni.request联网,而是通过uniCloud.callFunction调用云函数。

callFunction方式避免了服务器提供域名,不暴露固定ip,减少被攻击的风险。

  • 对于uni-app前端而言,使用云对象会比使用callFunction云函数方式更为简单清晰。
  • 但对于非uni-app前端调用的场景,比如5+App、外部应用、服务器要调用云函数,或者uniCloud定时任务,此时不适合使用云对象,还是需要云函数。

uniCloud.callFunction可以在uni-app前端执行,也可以在uniCloud云函数中执行。也就是前端和云端都可以调用另一个云函数。

callFunction方法的参数和返回值如下:

callFunction方法

uniCloud.callFunction需要一个json对象作为参数,其中包含2个字段

字段类型必填说明
nameString云函数名称
dataObject客户端需要传递的参数

返回json

字段类型说明
resultObject云函数中代码return的返回结果
requestIdString云函数请求序列号,用于错误排查,可以在uniCloud web控制台的云函数日志中查到
headerObject服务器header信息
errCodeNumber或String服务器错误码
successbool执行是否成功

注意:

  • HBuilderX本地运行云函数时不返回header,需要在云端运行云函数才会返回
  • callFunction内部会使用uni.request来发送请求,如果有对uni.request写拦截器务必准确区分要拦截的内容

返回格式,下文有详细解读?详见

前端示例代码

假使云服务空间有一个云函数名为“hellocf”,那么前端可以通过如下方式调用这个云函数

// promise方式
uniCloud.callFunction({
    name: 'hellocf',
    data: { a: 1 }
  })
  .then(res => {});

// callback方式
uniCloud.callFunction({
	name: 'hellocf',
	data: { a: 1 },
	success(){},
	fail(){},
	complete(){}
});

云函数的入参

客户端callFunction调用云函数时,云函数通过入参接收客户端数据,通过头信息上下文获取客户端信息,经过业务逻辑处理后给客户端返回结果。

假使客户端代码调用云函数hellocf,并传递了{a:1,b:2}的数据,

// 客户端调用云函数并传递参数
uniCloud.callFunction({
    name: 'hellocf',
    data: {a:1,b:2}
  })
  .then(res => {});

?那么云函数侧的代码如下,将传入的两个参数求和并返回客户端:

// hellocf云函数index.js入口文件代码
'use strict';
exports.main = async (event, context) => {
	//event为客户端上传的参数
	let c = event.a + event.b
	return {
		sum: c
	} // 通过return返回结果给客户端
}

云函数的传入参数有两个,一个是event对象,一个是context对象。

  • event指的是触发云函数的事件。当客户端调用云函数时,event就是客户端调用云函数时传入的参数。
  • context?对象包含了本次请求的上下文,包括客户端的ip、ua、appId等信息,以及云函数的环境情况、调用来源source等信息。

event对象

event对象,可以理解为客户端上行参数中的json对象。在使用uni-id且登录成功后,会自动多添加了一个uniIdToken属性。

可以通过?event.uniIdToken?获取 uni-id 的 token,如下:

'use strict';
exports.main = async (event, context) => {
  let token = event.uniIdToken // 客户端uni-id token
}

所以开发者需注意,自己上行的参数对象不要包含uniIdToken属性,避免同名冲突。?

入参的体积限制

云函数上行的参数内容不能传太大。

  • 支付宝小程序云接收参数大小不可超过6MB
  • 阿里云event大小不可超过1MB
  • 腾讯云event大小不可超过5MB

context对象

  • context?对象包含了本次请求的上下文,包括客户端的ip、ua、appId等信息,以及云函数的环境情况、调用来源source等信息。

context对象的属性清单如下:

属性名称类型说明
SPACEINFOobject服务空间信息
?|- spaceIdstring服务空间id
?|- providerstring服务空间供应商:alipay|aliyun|tencent
?|- useOldSpaceIdboolean当前获取的服务空间id是否为迁移前的服务空间id,新增于HBuilderX 3.6.13
SOURCEstring云函数调用来源?详见
FUNCTION_NAMEstring获取云函数名称
FUNCTION_TYPEstring获取云函数类型,对于云函数来说,这里一定会返回cloudfunction,新增于HBuilderX 3.5.1。
CLIENTIPstring客户端IP。如果调用来源是其他服务器,会返回调用方的ip
CLIENTUAstring客户端userAgent。注意非本地运行环境下客户端getSystemInfoSync也会获取ua参数并上传给云函数,但是云函数会从http请求头里面获取ua而不是clientInfo里面的ua
uniIdTokenstring客户端uni-id token字符串,新增于HBuilderX 3.5.1。
requestIdstring当前请求id,新增于HBuilderX 3.5.5。

除了上述属性,如果是uni-app客户端通过callfunction访问云函数,那么context还会追加一批客户端信息。

  • HBuilderX 3.4.9前,context 添加了一批大写属性,如APPID、OS。
  • HBuilderX 3.4.9起,context 的属性包括前端API?uni.getSystemInfo?的所有属性。比如appId、osName,均以驼峰方式命名。这些属性较多,且可能跟随前端API更新而变化,具体详见?uni.getSystemInfo

为了保持向下兼容,新版并没有去掉老版那些大写属性的客户端信息,但文档标注为以废弃。对于新版HBuilderX用户而言,请使用?uni.getSystemInfo?返回的驼峰属性。

HBuilderX 3.4.9起,context 的属性还可以打印出channelscene,即App的渠道包标记和小程序场景值。但这个功能属于未完成功能,开发者暂不使用这2个属性,后续会升级完善。目前如开发者需要这2个属性,请自行在客户端使用uni.getLaunchOptionsSync上传。

'use strict';
exports.main = async (event, context) => {
	//event为客户端上传的参数
  //...
  //context中可获取客户端调用的上下文
  let clientIP = context.CLIENTIP // 客户端ip信息
  let spaceInfo = context.SPACEINFO // 当前环境信息 {spaceId:'xxx',provider:'tencent'}
  let source = context.SOURCE // 云函数调用来源
  // 以下属性只有使用uni-app以callFunction方式调用才能获取,即context.SOURCE=="client",调用方不是uni-app客户端则没有相应数据
  let appid = context.appId // manifest.json中配置的appid
  let deviceId = context.deviceId // 客户端标识,新增于HBuilderX 3.1.0,同uni-app客户端getSystemInfo接口获取的deviceId
	//... //其它业务代码
}

获取云函数调用来源

context.SOURCE,返回云函数调用来源,它的值域为:

取值解释
client客户端callFunction方式调用
http云函数url化方式调用
timing定时触发器调用
function由其他云函数callFunction调用
server由uniCloud管理端调用,HBuilderX里上传并运行

?

'use strict';
exports.main = async (event, context) => {
  let source = context.SOURCE // 当前云函数被何种方式调用
  // client   客户端callFunction方式调用
  // http     云函数url化方式调用
  // timing   定时触发器调用
  // server   由管理端调用,HBuilderX里上传并运行
  // function 由其他云函数callFunction调用
}

注意事项

  • 客户端上报的信息在理论上存在被篡改可能,实际业务中应验证前端传来的数据的合法性
  • context.PLATFORM的取值,有?app?和?app-plus?两种情况。
    • uni-app的vue3版本取值为app
    • vue2版本,在uni-app 3.4.9之前,取值为?app-plus,uni-app 3.4.9起,该值修改为了app

除了CLIENTIP外,其他客户端信息只有使用uni-app客户端以callFunction方式调用才能获取。如果云函数url化后被uni-app通过request调用,也没有客户端信息。

在云函数URL化的场景无法获取客户端平台信息,可以在调用依赖客户端平台的接口接口之前(推荐在云函数入口)通过修改context.PLATFORM手动传入客户端平台信息供其他插件(如:uni-id)使用

例:

exports.main = async (event, context) => {
	context.PLATFORM = 'app'
}

?

云函数的返回格式

普通云函数返回给客户端的是json格式数据。返回结果包裹在result下。

前端发起callFunction到云端接收参数并响应,然后反馈前端,前端接收,完整流程代码如下:

// 客户端发起调用云函数hellocf,并传入data数据
uniCloud.callFunction({
	name: 'hellocf',
	data: {a:1,b:2}
}).then((res) => {
	console.log(res.result) // 结果是 {sum: 3}
}).catch((err) => {
	console.error(err)
})

?

// 云函数hellocf的代码,接收到客户端传递的data,并对其中a和b相加返回给客户端
'use strict';
exports.main = async (event, context) => {
	//event为客户端上传的参数
	console.log('event : ', event)
	//返回数据给客户端
	return {sum : event.a + event.b}
};

那么客户端得到的res结构如下?

{
	"errCode": 0,
	"errMsg": "",
	"header": {
		"access-control-expose-headers": "Date,x-fc-request-id,x-fc-error-type,x-fc-code-checksum,x-fc-invocation-duration,x-fc-max-memory-usage,x-fc-log-result,x-fc-invocation-code-version"
		"content-disposition": "attachment"
		"content-length": "38"
		"content-type": "application/json"
		"date": "Sat, 25 Jun 2022 19:28:34 GMT"
		"x-fc-code-checksum": "92066386860027743"
		"x-fc-instance-id": "c-62b761c4-5a85e238b3ce404c817d"
		"x-fc-invocation-duration": "23"
		"x-fc-invocation-service-version": "LATEST"
		"x-fc-max-memory-usage": "66.61"
		"x-fc-request-id": "80854b93-b0c7-43ab-ab16-9ee9f77ff41e"
		"x-serverless-request-id": "ac1403831656185314624173902"
		"x-serverless-runtime-version": "1.2.2"
	}
	"requestId": "ac1403831656185314624173902"
	"result": {sum: 3}
	"success": true
}

其中result是开发者云函数代码返回的数据,其余是云平台返回的。

注意:HBuilderX本地运行云函数时,如果没有系统错误,则只返回result,其他需要在云端运行云函数才会返回。

  • errCode为0时,success也是true。
    • 表示云函数在系统层面没有运行错误。可以正常返回result。前端callFunction会进入success回调
    • 如果开发者的业务有报错,可以在 result 里返回 errCode 和 errMsg。
  • errCode不为0时,success为false。
    • 表示云函数在系统层面报错了,比如联网失败、云函数超时、内存超限等错误。前端callFunction会进入fail回调
    • 发生系统错误时 result 里无法正常返回业务错误。errCode不为0时,还会返回errMsg。
  • requestId是云函数的请求id,线上运行时,可以在uniCloud web控制台的云函数日志中查看运行日志。
  • header是云厂商的一些信息,阿里云和腾讯云不同,上面示例代码是阿里云的header。

uniCloud响应体规范

为了方便统一拦截错误,推荐开发者使用?uniCloud响应体规范

业务报错时,在 result 里返回 errCode 和 errMsg。如下:

?

'use strict';
exports.main = async (event, context) => {
	//event为客户端上传的参数
	console.log('event : ', event)
	if (!event.a) {
		return {errCode : 1,errMsg : "参数a不能为空"}
	}
	if (!event.b) {
		return {errCode : 2,errMsg : "参数b不能为空"}
	}
	const c = event.a + event.b
	if (isNaN(c)) {
		return {errCode : 3,errMsg : "参数a和b无法求和"}
	}
	//返回数据给客户端
	return {sum:c,errCode : 1,errMsg : "0"}
};

?

总结案例

新建云函数

?

使用云函数?

    onLoad() {
      // 传统使用接口:
      // uni.request({
      //   url:""
      // })
 
      // uniCloud使用:
      uniCloud.callFunction({
        name: 'myCloudFun'
      }).then(res => {
        console.log(res)
      })
    },

展示?

文章来源:https://blog.csdn.net/qq_63358859/article/details/135581008
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。