diff --git a/docs/uniCloud/cf-callfunction.md b/docs/uniCloud/cf-callfunction.md index 5b3a2abc206ec23cebcce359fcecb91a03e39f8c..9e1ecfc0bdb84a7bf03683922bfff60403976978 100644 --- a/docs/uniCloud/cf-callfunction.md +++ b/docs/uniCloud/cf-callfunction.md @@ -26,13 +26,15 @@ callFunction方式避免了服务器提供域名,不暴露固定ip,减少被 |字段 |类型 |说明 | |:-: |:-: |:-: | -|result |Object |云函数返回结果 | +|result |Object |云函数中代码return的返回结果 | |requestId |String |云函数请求序列号,用于错误排查,可以在uniCloud web控制台的云函数日志中查到 | |header |Object |服务器header信息 | |errCode |Number或String |服务器错误码 | |success |bool |执行是否成功 | -注意:HBuilderX本地运行云函数时只返回result,其他需要在云端运行云函数才会返回 +注意:HBuilderX本地运行云函数时只返回`result`,其他需要在云端运行云函数才会返回 + +返回格式,下文有详细解读 [详见](?id=returnformat) **前端示例代码** @@ -60,7 +62,7 @@ uniCloud.callFunction({ 客户端callFunction调用云函数时,云函数通过入参接收客户端数据,通过头信息上下文获取客户端信息,经过业务逻辑处理后给客户端返回结果。 -假使客户端代码调用云函数hellocf,并传递了{a:1,b:2}的数据, +假使客户端代码调用云函数`hellocf`,并传递了`{a:1,b:2}`的数据, ```js // 客户端调用云函数并传递参数 uniCloud.callFunction({ @@ -76,78 +78,91 @@ uniCloud.callFunction({ 'use strict'; exports.main = async (event, context) => { //event为客户端上传的参数 + let c = event.a + event.b return { - sum:event.a + event.b + sum: c } // 通过return返回结果给客户端 } ``` 云函数的传入参数有两个,一个是`event`对象,一个是`context`对象。 - `event`指的是触发云函数的事件。当客户端调用云函数时,`event`就是客户端调用云函数时传入的参数。 -- `context` 对象包含了本次请求的上下文,包括客户端的操作系统(`os`)、运行平台(`platform`)、应用信息(`appid`) +- `context` 对象包含了本次请求的上下文,包括客户端的ip、ua、appId等信息,以及云函数的环境情况、调用来源source等信息。 + +### event对象 + +event对象,可以理解为客户端上行参数中的json对象。在使用`uni-id`且登录成功后,会自动多添加了一个`uniIdToken`属性。 -如下是一个示例: +可以通过 `event.uniIdToken` 获取 uni-id 的 token,如下: ```js 'use strict'; exports.main = async (event, context) => { - //event为客户端上传的参数 - //... - //context中可获取客户端调用的上下文 - let clientIP = context.CLIENTIP // 客户端ip信息 - let clientUA = context.CLIENTUA // 客户端user-agent - let spaceInfo = context.SPACEINFO // 当前环境信息 {spaceId:'xxx',provider:'tencent'} - // 以下四个属性只有使用uni-app以callFunction方式调用才能获取,调用方不是uni-app客户端则没有相应数据 - let os = context.OS //客户端操作系统,返回值:android、ios 等 - let platform = context.PLATFORM //运行平台,返回值为 mp-weixin、app-plus等。注意:vue3版本uni-app将app-plus修改为了app,此处为保证旧版本兼容性未进行统一,推荐后续在业务中都使用app作为客户端标识 - let appid = context.APPID // manifest.json中配置的appid - let deviceId = context.DEVICEID // 客户端标识,新增于HBuilderX 3.1.0,同uni-app客户端getSystemInfo接口获取的deviceId - //... //其它业务代码 + let token = event.uniIdToken // 客户端uni-id token } ``` -**注意:下面所有的“客户端”均是相对于云函数而言,如果你使用自己的服务器调用云函数,此时客户端是指你的服务器** +所以开发者需注意,自己上行的参数对象不要包含uniIdToken属性,避免同名冲突。 -### 获取用户token@client-token +**入参的体积限制** -如果客户端在storage内存储了uni_id_token,在使用callFunction请求云函数时会自动将此token传递到云端,云端可以通过以下方式获取: +云函数上行的参数内容不能传太大。 -```js -'use strict'; -exports.main = async (event, context) => { - let token = event.uniIdToken // 客户端uni-id token -} -``` +- 阿里云event大小不可超过1MB +- 腾讯云event大小不可超过6MB -### 获取客户端IP@clientip +### context对象 -```js -'use strict'; -exports.main = async (event, context) => { - let clientIP = context.CLIENTIP // 客户端ip信息 -} -``` +- `context` 对象包含了本次请求的上下文,包括客户端的ip、ua、appId等信息,以及云函数的环境情况、调用来源source等信息。 -### 获取客户端user-agent@client-user-agent +context对象的属性清单如下: -```js -'use strict'; -exports.main = async (event, context) => { - let clientUA = context.CLIENTUA // 客户端user-agent信息 -} -``` +|属性名称 |类型 |说明 | +|-- |-- |-- | +|SPACEINFO |object |服务空间信息 | +| |- spaceId |string |服务空间id | +| |- provider |string |服务空间供应商:aliyun|tencent | +|SOURCE |string |云函数调用来源 [详见](?id=context-source) | +|FUNCTION_NAME |string |获取云函数名称 | +|CLIENTIP |string |客户端IP。如果调用来源是其他服务器,会返回调用方的ip| -### 获取服务空间信息@context-space-info +除了上述属性,如果是uni-app客户端通过callfunction访问云函数,那么context还会追加一批客户端信息。 +- HBuilderX 3.4.9前,context 添加了一批大写属性,如APPID、OS。 +- HBuilderX 3.4.9起,context 的属性包括前端API `uni.getSystemInfo` 的所有属性。比如appId、osName,均以驼峰方式命名。这些属性较多,且可能跟随前端API更新而变化,具体详见 [uni.getSystemInfo](/api/system/info.html#getsysteminfo) + +为了保持向下兼容,新版并没有去掉老版那些大写属性的客户端信息,但文档标注为以废弃。对于新版HBuilderX用户而言,请使用 `uni.getSystemInfo` 返回的驼峰属性。 + +示例: ```js '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 +context.SOURCE,返回云函数调用来源,它的值域为: + +|取值 |解释 | +|-- |-- | +|client |客户端callFunction方式调用 | +|http |云函数url化方式调用 | +|timing |定时触发器调用 | +|function |由其他云函数callFunction调用 | +|server |由uniCloud管理端调用,HBuilderX里上传并运行| + ```js 'use strict'; exports.main = async (event, context) => { @@ -160,30 +175,14 @@ exports.main = async (event, context) => { } ``` -### 其他客户端信息@client-info - -> HBuilderX 3.4.9起,可以获取所有客户端`getSystemInfo`返回的客户端信息,详细字段列表参考:[getSystemInfo](https://uniapp.dcloud.net.cn/api/system/info.html#getsysteminfo) - -```js -'use strict'; -exports.main = async (event, context) => { - let os = context.OS //客户端操作系统,返回值:android、ios 等 - let platform = context.PLATFORM //运行平台,返回值为 mp-weixin、app等。注意老版曾使用app-plus,具体见下 - let appid = context.APPID // manifest.json中配置的appid - let deviceId = context.DEVICEID // 客户端标识,新增于HBuilderX 3.1.0,同uni-app客户端getSystemInfo接口获取的deviceId -} -``` - **注意事项** - 客户端上报的信息在理论上存在被篡改可能,实际业务中应验证前端传来的数据的合法性 - `context.PLATFORM`的取值,有 `app` 和 `app-plus` 两种情况。 * uni-app的vue3版本取值为`app` * vue2版本,在uni-app 3.4.9之前,取值为 `app-plus`,uni-app 3.4.9起,该值修改为了`app` -- 阿里云event大小不可超过1MB,腾讯云event大小不可超过6MB - -客户端信息只有使用uni-app客户端以callFunction方式调用才能获取,由客户端传递到云函数。如果云函数url化后被uni-app通过request调用,也没有客户端信息。 +除了CLIENTIP外,其他客户端信息只有使用uni-app客户端以callFunction方式调用才能获取。如果云函数url化后被uni-app通过request调用,也没有客户端信息。 在云函数URL化的场景无法获取客户端平台信息,可以在调用依赖客户端平台的接口接口之前(推荐在云函数入口)通过修改context.PLATFORM手动传入客户端平台信息供其他插件(如:uni-id)使用 @@ -195,11 +194,11 @@ exports.main = async (event, context) => { } ``` -## 云函数的返回格式 +## 云函数的返回格式@returnformat 普通云函数返回给客户端的是json格式数据。返回结果包裹在result下。 -前端发起callFunction到云端接收参数并响应,然后反馈前端,然后前端接收参数的完整流程代码如下: +前端发起callFunction到云端接收参数并响应,然后反馈前端,前端接收,完整流程代码如下: ```js // 客户端发起调用云函数hellocf,并传入data数据 @@ -228,7 +227,8 @@ exports.main = async (event, context) => { 那么客户端得到的res结构如下 ```json { - "errCode": 0 + "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" @@ -252,13 +252,23 @@ exports.main = async (event, context) => { 其中`result`是开发者云函数代码返回的数据,其余是云平台返回的。 -注意:HBuilderX本地运行云函数时只返回`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响应体规范`,[详见](uniCloud/cf-functions.md?id=resformat) +为了方便统一拦截错误,推荐开发者使用 [uniCloud响应体规范](cf-functions.md?id=resformat) + +业务报错时,在 result 里返回 errCode 和 errMsg。如下: -如果按照uniCloud响应体规范,那么云函数代码应该修正为return信息补充errCode和errMsg。如下: ```js 'use strict'; exports.main = async (event, context) => {