# Introduction

A cloud function is a JavaScript code that runs on the cloud and is an extension based on Node.js.

On the basis of the conventional Node API, uniCloud's cloud function environment has a built-in uniCloud object, which has built-in various APIs such as network and database. It doesn't matter if the developer has not learned Node.js, just read the uniCloud documentation and master the API of the uniCloud object.

Each cloud function is a js package. When the cloud function is called, the serverless scheduling system allocates hardware resources to start a node environment to run the cloud function.

Each cloud function is a directory, in which common cloud functions have an index.js entry file, and cloud object entry files are index.obj.js.

The simplest cloud function only needs this entry js file, and you can write code in it. Of course, you can also require other js and json files in the cloud function directory in this js.

The configuration file of the cloud function is the same as the npm specification, and a package.json can be created in the cloud function directory to store the configuration. uniCloud cloud function extends package.json and adds some unique configuration items. See details

After the cloud function is started, the instance will be retained for a period of time (such as 15 minutes). If the cloud function has not been called again after the retention period expires, the instance will be released. So cloud functions have the concept of cold start. However, since the startup of js instances is faster than php and java, js is more suitable for serverless methods.

Precautions

  • The commonjs specification is used in the cloud function, import and export cannot be used, refer to: commonjs module
  • When different projects use the same service space, cloud functions with the same name cannot be used. Cloud functions with the same name override each other.
  • 在HBuilderX创建云函数时,如果新云函数与服务器上已存在同名云函数,会用新函数覆盖。所以应先选择从服务空间下载云函数。
  • 单个云函数大小限制为10M(包含node_modules),过大的云函数影响运行性能,也会增加计费的gbs。同时支付宝小程序云与腾讯云支持在云端安装node_modules,此时不占用云函数体积。
  • uniCloud的阿里云版与支付宝小程序云版,暂不可使用相对路径读取文件(比如fs.readFileSync('./info.txt')),可以使用绝对路径fs.readFileSync(path.resolve(__dirname,'./info.txt'))

# Classification of cloud functions

Cloud functions have several sub-concepts, including common cloud functions, cloud objects, public modules, action cloud functions of clientDB, and uniCloud extension library.

  • Cloud function: communicate with the client through the traditional json interface, and the client uses uniCloud.callfunction("") to call the cloud function
  • Cloud object: It is operated by importing objects through the front end, and the client uses uniCloud.importObject("") to import cloud objects. For details, see Cloud Object
  • Common module: used for different cloud functions/cloud objects, extracting and sharing the same code, see [public module document](/uniCloud/cf-functions?id=%E5%85%AC%E5%85%B1% E6%A8%A1%E5%9D%97)
  • action cloud function (not recommended): designed to make up for the limitations of the clientDB client directly operating the database, see clientDB action documentation for details. Starting from HBuilderX 3.6.11, it is recommended to use database trigger instead of action cloud function.
  • uniCloud extension library: designed to cut and control the volume of cloud functions, some less commonly used functions such as Redis, are independent optional extension libraries to avoid increasing the volume of each cloud function, see uniCloud extension library

The cloud functions of the uniCloud project in HBuilderX are all in the uniCloud/cloudfunctions directory of the project, and the directory structure is as follows:

	
|——— cloudfunctions               云函数目录
|   │───common                    云函数公用模块目录 详情
|   |   └──hello-common           云函数公用模块
|   |      │──index.js            公用模块代码
|   |      └──package.json        公用模块package.json
|   │───uni-clientDB-actions      (推荐用数据库触发器替代action云函数)
|   │      └──new_action.js       clientDB action代码 详情
|   │───function-name             云函数目录
|   │     │──index.js             云函数代码
|   │     └──package.json         包含云函数的配置信息,如url化、定时设置、可用内存等内容 详情
|   └───object-name               云对象目录
|         │──index.obj.js         云对象代码
|         └──package.json         包含云对象的配置信息,可用内存等内容 详情
	

# Communication between client and cloud function

When the uni-app client communicates with the traditional server, the ajax request method of uni.request is used. It is no longer used under uniCloud, and there is a better cloud-integrated communication method.

In the uniCloud system, there are four ways for the cloud function communication between the client and the server:

Traditional restful method callfunction method cloud object method clientDB method
Brief By configuring cloud function URL, the cloud function is converted into a traditional http link The cloud function does not come with an http link by default Upgrade the functional call of the call function to a modular Object call client directly operates the cloud database
Front-end calling method Traditional ajax The uni-app client calls the cloud function through uniCloud.callFunction(functionname) The uni-app client imports a cloud object through uniCloud.importObject(objectname), and uses this object directly Method The uni-app client accesses the uniCloud database through <uniCloud-db> component or uniCloud.database() API. It also supports adding server logic with action cloud functions
Applicable Scenarios You need to register your own domain name for http links. URLification is deprecated if the front end is a uni-app. If a non-uni-app system needs to access cloud functions, it can only be URLized Compared with cloud function URLs, callfunction is more secure and serverless, does not expose domain names and IPs, is not afraid of attacks, and does not need to register domain names uni-app 3.4 onwards support. Compared to the call function way. The code is more streamlined, the logic is clearer, and the development is more efficient If the server request initiated by the uni-app front end is mainly for querying or operating the database, it is recommended to use the clientDB method

Cloud functions are the foundation of uniCloud. In essence, clientDB and cloud objects are optimized for specific scenarios based on cloud functions.

  • The scenario targeted by clientDB is database operation, which optimizes the need to write less or no server code
  • The scene targeted by the cloud object is the communication method with the uni-app client for non-database operations or database operations that are not suitable for front-end exposure. It optimizes the code structure, making it more streamlined and simple

# clientDB mode

Visual experience code example

clientDB is divided into API mode and component mode, and the API mode is used here to demonstrate

// The client js directly operates the cloud database and queries the data in the list table. No server code required
const db = uniCloud.database() // 获取云数据库的引用
db.collection('list').get()
  .then((res)=>{
    // res is the database query result
  }).catch((err)=>{
    console.log(err); 
  })

Due to the length of the article, please refer to the document clientDB to learn clientDB

  • When clientDB is applicable:

If the client uses uni-app development, and the request to the uniCloud service space is mainly for operating the cloud database (regardless of adding, deleting, modifying and checking), then it is recommended to use the clientDB method, and the uni-app client directly operates the cloud database.

If you need to execute some cloud logic while operating the database: HBuilderX 3.6.11 used the action cloud function; starting from HBuilderX 3.6.11, it is recommended to use database trigger instead of the action cloud function.

  • Situations where clientDB is not applicable:
  1. Request not to operate the cloud database, such as sending requests to external web systems, operating redis, deleting cloud files, etc.;
  2. The operating cloud database request does not want to be exposed on the front end;
  3. The number of database tables and fields is large and the number of interfaces is small. The workload of configuring permissions for each data exceeds the workload of controlling a few interface permissions;
  4. The permission system is very complicated, and there are many other permission conditions or dynamic permissions besides users and administrators. At this time, the complexity of writing code in schema.json/schema.ext.js exceeds that of writing interfaces.

# Cloud Object Mode

The biggest difference between cloud objects and clientDB is that cloud objects encapsulate database operations (and other logic) in cloud object methods.

It does not need to develop server code like clientDB, it still needs to write code separately on the client and the cloud. But its application scenarios are not limited. The above situations where clientDB is not applicable can be solved by using cloud objects.

Visual experience code example

Cloud cloud object code, cloud object name: testco, has a sum method

module.exports = {
	sum(a, b) {
		// The validity check of a and b is omitted here
		return a + b
	}
}

Then in the js of the client, import the testco object and call its sum method

const testco = uniCloud.importObject('testco') //第一步导入云对象
async function sum () { //注意方法或生命周期需使用async异步方式
	try {
		const res = await testco.sum(1,2) //导入云对象后就可以直接调用该对象的方法了,注意使用异步await
		console.log(res) // 结果是3
	} catch (e) {
		console.log(e)
	}
}

Due to the length of the article, please refer to the document Cloud Object for learning cloud objects

clientDB and cloud objects can be mixed:

  1. For example, uni-id-pages is officially provided, which is a login and registration system based on cloud objects. Developers can export this plug-in to process the account system, and then the remaining business is not complicated. , you can use clientDB to get it done.
  2. The user end and admin end of a business can also be different technology stacks. For example, the business side has complex dynamic permissions, and the management side is only used by an admin administrator, then it will be very efficient to use schema2code on the admin side, and these technologies are all based on clientDB.

# Common cloud function callFunction method

  • Situations where ordinary cloud functions are applicable:

Before HBuilderX 3.5.2, only ordinary cloud functions can be used when URLization and scheduled operation are required; in HBuilderX 3.5.2+, cloud objects also support URLization and scheduled operation.

Officially, developers are not recommended to use cloud functions. If there are related needs, it is recommended to use cloud objects instead of cloud functions.

At present, the official framework of the router mode based on cloud objects has not been provided, and a third-party framework can be used if there are related needs.

Visual experience code example

// The client initiates a call to the cloud function hellocf and passes in data
uniCloud.callFunction({
	name: 'hellocf',
	data: {a:1,b:2}
}).then((res) => {
	console.log(res.result) // 结果是 {sum: 3}
}).catch((err) => {
	console.error(err)
})
// The code of the cloud function hellocf receives the data passed by the client, adds a and b and returns it to the client
'use strict';
exports.main = async (event, context) => {
	//event is the parameter uploaded by the client
	console.log('event : ', event)
	//The validity check of event.a and event.b is omitted here
	//return data to client
	return {sum : event.a + event.b}
};

Due to the long space, please refer to the document [Cloud function call function method](/uniCloud/cf-call function)

# Cloud function URL method

It is possible to have a cloud function/cloud object generate an HTTP URL. In this way, non-uni-app applications can communicate with cloud functions/cloud objects through ajax requests.

Perform URLization configuration on the uniCloud web console.

Due to the length of the document, please refer to the document URLization of cloud functions.

# 云函数请求中的中间状态通知通道

云函数在执行期间可以将中间状态发送给客户端,详情参考:云函数请求中的中间状态通知通道

# uniCloud response body specification

uniCloud response body specification (uniCloud response format) is a suggested format formulated by DCloud for the server to return json data to the client.

Cloud objects, clientDB, and uni-id public modules all support this specification.

origin

The data format returned by the uniCloud server to the client is generally json, but there is no agreement on the specific format of json. For example, when returning an error code, is it called code or errCode? Is the error content message or errMsg? How is internationalization of content handled?

Without a unified format, effective network interceptors cannot be written on the client side, and errors cannot be handled uniformly.

In addition, if the data format returned by the cloud varies greatly with different plug-ins, it will be very troublesome for users to integrate these plug-ins. Internationalization is even more impossible to land.

For this reason, DCloud has launched the uniCloud response body specification.

In order to be unified with the API error callback style of the uni-app front end, the cloud return information (especially when an error is reported) defined by the uniCloud response body specification should include errCode and errMsg.

# Error specifications for HBuilderX 3.6.10 and later versions

The error specification is inherited from uni error specification

# Error specifications for versions prior to HBuilderX 3.6.10

// return value on failure
{
  "errCode": 'uni-id-account-banned',
  "errMsg": '账号被禁用'
}
  • errCode

errCode should return the number 0 on success, and a "string" starting with the plugin id on failure, each word separated by a hyphen (-). This provision is made to prevent duplication of error codes between different plugins

Take 'uni-id-account-banned' error code as an example, uni-id is the plugin id, and account-banned is the error abbreviation.

If the business development code does not publish the plug-in market, in order to avoid conflicts when downloading a plug-in in a market, it is recommended to use a string that does not contain "-" as the errCode (all plug-in IDs in the plug-in market must contain "-").

In the future, uniCloud will provide the function of automatically internationalizing errMsg according to errCode. Developers only need to ensure that the return value of the cloud function meets the uniCloud response body specification.

  • errMsg

errMsg is used to store specific error messages, including error messages displayed to developers and end users

# request successful response

除此之外响应体规范还包含newToken字段,用于token的自动续期(云对象接收含有newToken的响应后会自动更新storage内存储的uni_id_tokenuni_id_token_expired,此行为新增于HBuilderX 3.4.13)。开发者仅在自行调用uni-id-common的checkToken等会产生新token的接口时才需要返回新token,uni-app客户端和uni-id-co之间会自动管理token及续期。

An example of uniCloud response body is as follows:

// successful return value
{
  "errCode": 0,
  "errMsg": '登录成功',
  "uid": 'xxx', // 其他信息
  "newToken": { // 用于下发新token给客户端
	  "token": 'xxx',
	  "tokenExpired": 'xxx'
  }
}

Use the code block returnu in HBuilderX to quickly enter the following code (HBuilderX 3.4.0 and above):

return {
	errSubject: '', // HBuilderX 3.6.10新增
	errCode: 0,
	errMsg: ''
}

# uniCloud API list

Cloud Function supports standard APIs of js and nodejs, such as console.log(), setTimeout(), see also nodejs official website. Nodejs version, see Cloud Function Runtime Environment for details

In addition to the standard API, the uniCloud object is built into the cloud function environment, which expands a batch of new APIs. In actual development, the extended API of uniCloud is more commonly used. See below:

API Description
uniCloud.database() Cloud database object Details
uniCloud.databaseJQL() Use JQL syntax to operate the database in the cloud function For details, see, you need to add an extended library
uniCloud.redis() Use redis see details, need to add extension library
uniCloud.uploadFile() Cloud function to upload files to cloud storage details
uniCloud.downloadFile() The cloud function downloads the cloud storage file to the cloud function operating environment Details
uniCloud.deleteFile() Cloud function to delete cloud storage files details
uniCloud.getTempFileURL() Get the temporary path of the cloud storage file Details
uniCloud.customAuth() Use cloud vendor custom login, only Tencent Cloud supports Details
uniCloud.callFunction() Call another cloud function from a cloud function/cloud object see below
uniCloud.importObject() Call another cloud object in a cloud function/cloud object Details
uniCloud.httpclient Access other systems through http in the cloud function see below
uniCloud.httpProxyForEip Use the cloud vendor proxy to access http services (Alibaba Cloud's solution to WeChat needs fixed IP), only Alibaba Cloud cloud environment supports see details, added in HBuilderX 3.5.5
uniCloud.sendSms() To send a text message, you need to add an extension library see details
uniCloud.getPhoneNumber() To obtain a mobile phone number for one-click login, you need to add an extension library see details
uniCloud.init() Get the uniCloud instance of the specified service space see details
uniCloud.logger Print logs in the cloud function to the log system of uniCloud web console (not HBuilderX console) [details](rundebug.md?id= uniCloudlogger)
uniCloud.getRequestList Get the list of request IDs being processed in the current cloud function instance see details, added in HBuilderX 3.5.5
uniCloud.getClientInfos Get the list of client information corresponding to the request being processed in the current cloud function instance see, added in HBuilderX 3.5.5
uniCloud.getCloudInfos Get the list of cloud information corresponding to the request being processed in the current cloud function instance see details, added in HBuilderX 3.5.5

# Error object

When cloud functions call uniCloud interfaces (including requesting cloud functions, cloud objects, cloud storage, etc.), there may be scenarios where errors are thrown. At this time, uniCloud standard error objects (hereinafter referred to as uniCloudError) will be thrown. uniCloudError contains the following attributes

Property Type Required Description
errCode string yes error code
errMsg string yes error message
requestId string No Request Id, used for troubleshooting
detail object No This attribute will only exist when the cloud object actively returns the response body specification corresponding to the error

In addition, there are code attribute and message attribute on the uniCloudError object, both of which are not recommended.

# access the database

Cloud functions support access to databases under this service space or other authorized service spaces.

# Access other HTTP services

# uniCloud.httpclient.request

If you need to request other http services in the cloud function, use uniCloud.httpclient. Any HTTP and HTTPS protocol web service can be requested without additional dependencies. uniCloud.httpclient returns a urllib instance.

uniCloud.httpclient.request(URL,requestOptions)

requestOptions parameter description

Parameter name Type Required Default value Description
method String - GET HTTP request method, default: GET. Possible values: GET, POST, DELETE, PUT
data Object - - Sent data
dataAsQueryString Boolean - true Whether to forcibly convert data to queryString
content String | Buffer - - Manually set the payload of the request, and the data will be ignored after setting
stream ReadStream - - A readable data stream to send the request body
writeStream WriteStream - - A writable data stream that accepts response data
consumeWriteStream Boolean - true Whether to wait for the writeStream to be completely written before the response is completely received
files Array<ReadStream|Buffer|String> | Object | ReadStream | Buffer | String - - The uploaded file will use multipart after setting /form-data format. If the method is not set, the method will be automatically set to POST
contentType String - - The format of the uploaded data, if it is set to json, it will automatically set Content-Type: application/json in the header
nestedQuerystring Boolean - - When converting data to queryString, nested Objects are not supported by default. If this option is set to true, nested Objects are supported
dataType String - - Returned data format, optional values are 'json' (returned data is converted to JSON), 'text' (returned data is converted to string), '' (returned data is not processed, default)
fixJSONCtlChars Boolean - false Process Control Characters in response results before JSON.parse
headers Object - - request headers
timeout Number | Array - 5000 Timeout setting. When set as an array, the first item is the request timeout, and the second item is the return timeout. When set to a number, it is equivalent to setting the request timeout and return timeout at the same time, that is, the effect of timeout:3000 is equal to timeouut:[3000,3000]
auth String - - Basic Authentication parameter, which must be set in user:password format
digestAuth String - - Digest Authentication parameter, which must be set in user:password format
agent http.Agent - - http agent, if not used, set to false
httpsAgent https.Agent - - https agent, if not used, it can be set to false
ca String|Buffer|Array - - Certificate content
rejectUnauthorized Boolean - true Whether to return an error when the certificate is not trusted
pfx String|Buffer - - Includes private key, certificate and CA certs, usually in PFX or PKCS12 format
key String|Buffer - - server's private key in PEF format
cert String|Buffer - - server certificate key in PEM format
passphrase String - - String of private key or pfx passphrase
ciphers String - - ciphers to use or exclude
secureProtocol String - - The method to use for SSL, eg SSLv3_method forces SSL version to 3.
followRedirect Boolean - false Whether to automatically redirect when a 3xx response is received
maxRedirects Number - 10 Maximum number of redirects
formatRedirectUrl Function - - Manually format url
beforeRequest Function - - Hook before request sending
streaming Boolean - false Whether to return the response stream directly. After streaming is enabled, HttpClient will return immediately after getting the response object res. At this time, result.headers and result.status can be read, but not read data data only.
gzip Boolean - false Whether to support gzip response format. After enabling gzip, HttpClient will automatically set the Accept-Encoding: gzip request header, and will automatically decompress the data with the Content-Encoding: gzip response header.
timing Boolean - false Whether to enable the time measurement of each phase of the request
enableProxy Boolean - false Whether to enable proxy
proxy String - null proxy address
lookup Function - - Custom DNS query function
checkAddress Function - - Check request address
trace Boolean - false whether to enable capture stack

Notice

By default, the request interface will not process the returned data, that is, if the dataType parameter is not passed, the data of the buffer type will be returned. If you want to automatically parse the returned result in json format, you need to set dataType to "json"

Example Code

const res = await uniCloud.httpclient.request(apiUrl, {
    method: 'POST',
    data: {
      test: 'testValue'
    },
    contentType: 'json', // 指定以application/json发送data内的数据
    dataType: 'json' // 指定返回值为json格式,自动进行parse
  })
console.log(res)

The returned data structure is as follows

{
	"data": {"name": "DCloud"}, // 响应内容
	"status": 200, // 状态码
	"headers": { // 响应头,仅作示例,不同服务器返回的有差异
		"date": "Tue, 29 Dec 2020 08:10:30 GMT",
		"content-type": "application/json",
		"content-length": "276",
		"connection": "keep-alive",
		"server": "gunicorn/19.9.0",
		"access-control-allow-origin": "*",
		"access-control-allow-credentials": "true"
	}
}

# uniCloud.request

新增于HBuilderX 3.8.10

为简化http请求的调用uniCloud新增了uni.request调用方法类似的http请求接口uniCloud.request

参数说明

属性 类型 必填 默认值 说明
url String 服务器接口地址
data Object/String/ArrayBuffer 请求的参数
header Object 请求头
method String GET 请求方法,GET、POST、DELETE、PUT
timeout Number 60000 超时时间,单位 ms
dataType String json 如果设为 json,会对返回的数据进行一次 JSON.parse,responseType非text时不生效
responseType String text 设置响应的数据类型。合法值:text、buffer
sslVerify Boolean true 验证 ssl 证书

返回值说明

属性 类型 必备 说明
statusCode number 开发者服务器接口地址
data Object/String/ArrayBuffer 响应结果
header Object 响应头

代码示例

const res = await uniCloud.request({
  url: 'https://example.com'
})
console.log(res.statusCode)
console.log(res.data)

# Send formdata type data

In actual business, there is often a need to use cloud functions to send formdata type data, such as some server interfaces provided by WeChat MiniApp(picture content security detection, recognition of picture QR codes, etc.), you can refer to the following examples to send

'use strict';
const fs = require('fs')
const path = require('path')
const FormData = require('form-data'); // 此form-data需要使用npm安装,地址:https://www.npmjs.com/package/form-data
exports.main = async (event, context) => {
  const form = new FormData()
  form.append('media', fs.readFileSync(path.resolve(__dirname, './test.jpg')), { // 为方便演示此处直接使用云函数目录下的test.jpg文件
    filename: 'test.jpg',
    contentType: 'image/jpeg'
  });
  form.append('otherParam', 'otherParam content');
  const res = await uniCloud.httpclient.request('https://httpbin.org/post', {
    method: 'POST',
    content: form.getBuffer(), // 请求内容
    headers: form.getHeaders(), // 请求头
    dataType: 'json' // 此处指定为json表示将此请求的返回值解析为json
  })
  return res
};

# 访问其他websocket服务

云函数无法作为websocket服务器使用,如有相关需求可以尝试使用uni-push 2.0实现,参考:uni-push 2.0

本章节内容介绍云函数如何作为websocket客户端使用。为简化调用方式uniCloud新增了uni.connectSocket方法类似的接口uniCloud.connectSocket

参数说明

参数名 类型 必填 说明
url String 服务器接口地址
header Object 请求头
protocols Array<String> 子协议数组

返回值说明

调用此接口返回SocketTask对象,见下一章节介绍

# SocketTask

# SocketTask.onMessage(CALLBACK)

监听 WebSocket 接受到服务器的消息事件

回调函数

WebSocket 接受到服务器的消息事件的回调函数

回调函数中的参数

属性 类型 说明
data String/Buffer 服务器返回的消息

# SocketTask.send(OBJECT)

通过 WebSocket 连接发送数据

参数

属性 类型 是否必填 说明
data String/Buffer 需要发送的内容

# SocketTask.close(OBJECT)

关闭 WebSocket 连接

参数

属性 类型 默认值 是否必填 说明
code Number 1000(表示正常关闭连接) 一个数字值表示关闭连接的状态号,表示连接被关闭的原因。
reason String 一个可读的字符串,表示连接被关闭的原因。

# SocketTask.onOpen(CALLBACK)

监听 WebSocket 连接打开事件

回调函数

WebSocket 连接打开事件的回调函数

回调函数中的参数

属性 类型 说明
data String/ArrayBuffer 服务器返回的消息

# SocketTask.onClose(CALLBACK)

监听 WebSocket 连接关闭事件

回调函数

WebSocket 连接关闭事件的回调函数

回调函数中的参数

属性 类型 说明
code number 一个数字值表示关闭连接的状态号,表示连接被关闭的原因。
reason string 一个可读的字符串,表示连接被关闭的原因。

# SocketTask.onError(CALLBACK)

监听 WebSocket 错误事件

回调函数

WebSocket 错误事件的回调函数

回调函数中的参数

属性 类型 说明
errMsg String 错误信息

# 示例

以下云函数示例代码,从websocket服务器获取消息拼接后返回给客户端,如果遇到错误会抛出错误

'use strict';
exports.main = async (event, context) => {
  const socketTask = uniCloud.connectSocket({
    url: 'wss://xxx.com'
  })
  socketTask.onOpen(async () => {
    await socketTask.send({
      data: 'send some data to server'
    })
    console.log('send data complete')
  })
  const SOCKET_TIMEOUT = 10000

  let error
  let result = ''
  socketTask.onMessage(({
    data
  } = {}) => {
    console.log('message data: ', data);
    result += data
    if (data === '[DONE]') {
      socketTask.close()
    }
  })
  socketTask.onError(function(err) {
    console.log('error', err)
    error = err
  })
  let isClosed = false
  const timeout = setTimeout(() => {
    if (isClosed) {
      return
    }
    error = new Error('socket timeout')
    socketTask.close()
  }, SOCKET_TIMEOUT)
  return new Promise((resolve, reject) => {
    socketTask.onClose(function(...args) {
      isClosed = true
      clearTimeout(timeout)
      console.log('close', ...args)
      if (error) {
        reject(error)
      } else {
        resolve({
          result
        })
      }
    })
  })
};

# Request and Environment API

Due to the existence of single instance with multiple concurrency, the instance-level uniCloud object has a one-to-many relationship with each request.

This also causes the context related to the request, such as client information, to be obtained through the request.

In order to better manage requests and request-related contexts, uniCloud provides the following batch of APIs.

# Get request id list

example

uniCloud.getRequestList()
// Return value: ['3228166e-3c17-4d58-9707-xxxxxxxx']

If Single Instance Multiple Concurrency is not configured, only one item will be returned in the array. After configuration, there may be multiple items, and the requestId of all concurrent requests will be returned.

When multiple items are returned, it is not clear which one in the array the current request is on the uniCloud object. So other methods are provided to get the current request:

  • Cloud object via this.getUniCloudRequestId(). Details
  • The cloud function uses the function's own parameter context. Details

# Get client information list #get-client-infos

Similarly, considering multiple concurrency of a single instance, uniCloud.getClientInfos() obtains client information is also an array.

const clientInfos = uniCloud.getClientInfos() 

return value

clientInfos = [{
  appId: '__UNI_xxxxx',
  requestId: '3228166e-3c17-4d58-9707-xxxxxxxx'
  // ...
}]

If single-instance multi-concurrency is not enabled, the array has only one item. In a single-instance multi-concurrency scenario, return a list of client information for all concurrent requests.

return value

The information returned by getClientInfos is based on the client's uni.getSystemInfo, with some additional information added.

In addition to the fields returned by getSystemInfo, the following information is also included

Property Name Type Description
requestId string Request Id, you can use this field to filter out the client information of the current request
clientIP string client ip
userAgent string client ua, note that the client getSystemInfoSync in non-local operating environment will also obtain the ua parameter and upload it to the cloud object, but the cloud object will obtain ua from the http request header instead of the ua in clientInfo
source string 调用来源,返回值见下。
scene string 场景值。客户端uni.getLaunchOptionsSync返回的scene参数,

Cloud function call source source, its value range is:

取值 说明
client uni-app客户端导入云对象调用
function 由其他云函数或云对象调用
http 云对象URL化后通过http访问调用
timing 定时任务调用云对象
server 云函数右键"上传并运行"

Precautions

  • In theory, the information reported by the client may be tampered with. In actual business, the legality of the data sent by the front end should be verified
  • In addition to clientIP, other client information is available only when using the uni-app client to access cloud functions or cloud objects in the way of callFunction or importObject
  • The cloud object is slightly different from the client platform obtained in the cloud function. The cloud function does not align the platform values of the vue2 and vue3 versions of the app platform. Vue2 is app-plus, and vue3 is app. Regardless of whether the client of the cloud object is vue2 or vue3, the platform obtained on the app platform is app. This point requires special attention when using uni-id. For details, see: uni-id document preferredAppPlatform

In addition to uniCloud.getClientInfos() API, the current client information can also be obtained directly in the cloud function context and cloud object this.

  • Cloud objects via this.getClientInfo(). Details
  • The cloud function uses the function's own parameter context. Details

# Get cloud information

As above, in order to be compatible with concurrent scenarios, getting cloud information uniCloud.getCloudInfos() also returns an array.

example

const cloudInfos = uniCloud.getCloudInfos() 
cloudInfos = [{
  provider: 'aliyun',
  spaceId: 'xxxxx',
  functionName: 'xxx',
  functionType: 'xxxx',
  requestId: '3228166e-3c17-4d58-9707-xxxxxxxx'
}]

return value

参数名 类型 必备 说明
provider string 服务空间供应商,支付宝小程序云:alipay,阿里云为:aliyun,腾讯云为:tencent
spaceId string 服务空间Id
functionName string 云函数名称
functionType string 云对象为cloudobject、云函数为cloudfunction
requestId string 请求Id,可以使用此字段筛选出当前请求的云端信息

In addition to uniCloud.getCloudInfos() API, in the cloud function context and cloud object this, you can also directly get the cloud information of the current request.

  • Cloud objects via this.getCloudInfo(). Details
  • The cloud function uses the function's own parameter context. Details

The above three APIs are all designed as arrays because of the multiple concurrency of a single instance. In fact, most developers do not use single-instance multi-concurrency.

When multiple concurrency of a single instance is not considered, you can also directly use the first array item in the getRequestList, getClientInfos, and getCloudInfos methods of uniCloud.

Or you can obtain relevant context information in the this of the cloud object and the context of the cloud function.

# Extension library

Among the APIs of uniCloud, the corresponding implementations of some APIs have a large code size, and these functions are not used by every cloud function. In order to facilitate developers to control the volume of cloud functions, the concept of uniCloud extension library is designed.

Developers can right-click the cloud function directory to manage public modules and extension library dependencies, and select the extension library to be loaded. The data corresponding to this visual interface is under the extensions field in package.json in the cloud function directory.

Note: If the extension library is not referenced, an error will be reported when using the corresponding API of uniCloud.

Currently supported extension libraries are as follows

  • JQL extension library [uni-cloud-jql]: used to use JQL syntax to operate the database in the cloud function, see: JQL extension library
  • redis extension library [uni-cloud-redis]: use redis in cloud functions, see: redis extension library
  • 发送短信扩展[uni-cloud-sms]:云函数中发送短信,详见:sms扩展
  • 一键登录与实人认证扩展[uni-cloud-verify]:手机App调用运营商一键登录服务时,云函数中获取到真实手机号, 详见:一键登录扩展库。核验终端操作者的真实身份,详见:uni实人认证
  • 统一推送服务扩展库[uni-cloud-push]:云函数内使用uni-push,详见:统一推送服务扩展库

The following is an example of cloud function package.json with the redis extension library enabled. Note that this file does not support comments, and the comments in the example below are for demonstration only

{
  "name": "add-article",
  "version": "1.0.0",
  "description": "新增文章",
  "main": "index.js",
	"extensions": {
		"uni-cloud-redis": {} // 配置为空对象即可,后续如有扩展参数会在此处配置
	}
}

# Common module

Cloud functions support public modules. The shared parts of multiple cloud functions/cloud objects can be separated into common modules, and then referenced by multiple cloud functions. Due to the length of the article, see details

# use npm

The running environment of cloud functions is Node.js, so we can use npm to install third-party dependencies.

Note: Alibaba Cloud currently only supports full upload of cloud functions (the entire node_modules folder is uploaded, and dependencies will be automatically installed locally before uploading, and node_modules in the cloud function directory will not be directly used), so developers are reminded to simplify dependencies. Otherwise, the upload time may be very slow each time, affecting the development experience. And a too large npm library affects the running performance of cloud functions.

腾讯云、支付宝小程序云会在上传云函数后自动安装需要的npm依赖。

Tips:

  • Currently, the upload package size of each cloud function is limited to 10M. If the npm package is large, Alibaba Cloud's overall upload mechanism will not be able to meet the demand. At this time, you can only choose Tencent Cloud, and let Tencent Cloud automatically install dependencies.

# Call cloud function in cloud function/cloud object

# Call three-party cloud functions or cloud objects

The usage is the same as that of the client to call the cloud function, which is still uniCloud.callfunction, but does not support the callback form.

Request parameters

Field Type Required Description
name String Yes Cloud function name.
data Object No Cloud function parameters.

Response parameters

Field Type Required Description
errCode String No Status code, if the operation is successful, it will not be returned.
errMsg String No Error description.
result Object No The execution result of the cloud function.
requestId String No Request serial number, used for troubleshooting.

Example Code

let callFunctionResult = await uniCloud.callFunction({
    name: "test",
    data: { a: 1 }
})

Notice

Since the caller is not a uni-app client, APIs such as the context of cloud functions and this.getClientInfo of cloud objects cannot obtain client information, including uni-id-token.

You can manually pass the token when interchanging cloud functions, or do not verify the user token when verifying that the call source (source) is a cloud function (function).

When cloud functions/cloud objects call each other, the caller will access the callee through the public network, and the access speed is not as good as directly executing the logic on the caller. Please make sure you really need this feature before using it.

Before the HBuilderX 3.4.0 version when the cloud function is right-clicked to run locally, the code inside callFunction will call the cloud function in the cloud instead of the local cloud function. This bug has been fixed in subsequent versions.

# The cloud function calls itself recursively

In addition to calling third-party cloud functions, in fact cloud functions can also call themselves recursively.

When the resources of a cloud function instance cannot meet the demand, or the timeout period is not enough. For example, if you want to send SMS to 100,000 users, and the SMS sending interface supports up to 50 mobile phone numbers at a time, you need to call the interface at least 2,000 times to complete; and a cloud function instance cannot complete 2,000 interface calls. This scenario can be realized by recursively calling cloud functions and decomposing tasks.

The sample code is as follows:

// Current cloud function name send-sms-cf
'use strict';
const db = uniCloud.database();
const dbCmd = db.command
const userTable = db.collection('uni-id-users')
exports.main = async (event, context) => {
	//execute business logic
	let res = await sendSms(event.before_id)
	if (res.errCode) {
		return res
	}else{
		// If no error is reported, let the current cloud function call the current cloud function (the cloud object is the same). Note: this is asynchronous
		uniCloud.callFunction({
			name: 'send-sms-cf',
			data: {
				before_id: res.before_id
			}
		}).catch(e=>{
			console.log(e.message);
		}).then(e=>{
			console.log(e.result);
		})
		
		// Wait for 500 milliseconds, giving time for a request to be sent out
		return await new Promise((resolve, reject) => {
			setTimeout(() => {
				resolve(res)
			}, 500)
		})
	}

	async function sendSms(before_id) {
		console.log('before_id',before_id);
		let where = {
			phone: dbCmd.exists(true),
			//.. Here you can write your own other conditions, such as users who have not logged in for a long time last_login_date < Date.now() - 3600*24*...
		}
		if(before_id){
			//High-performance paging query, the id of the last piece of data in the previous query is replaced by the starting id
			where._id = dbCmd.gt(before_id)
		}
		
		let res = await userTable.where(where)
			.limit(50)
			.orderBy("_id", "asc")
			.get()

		if (!res.data.length) {
			return {
				errCode: 'sendSms-invalid',
				errMsg: '结束,没有符合条件的接收者'
			}
		}
		let phoneList = res.data.map(item => item.phone)
		let sendSmsRes = await uniCloud.sendSms({
			phoneList,
			appid: '__UNI__xxxxxxx',
			smsKey: '****************',
			smsSecret: '****************',
			templateId: '100**', // 请替换为自己申请的模板id
			data: {
				text1: 'xxx',
				text2: 'xxx'
			}
		})
		if (sendSmsRes.errCode) {
			return sendSmsRes
		}
		return {
			errCode: 0,
			before_id: res.data[res.data.length - 1]._id
		}
	}
};

Note: If you accidentally write the recursive cloud function into an infinite loop, delete all the content of the cloud function, and upload it again to overwrite it

# Access other service spaces within the cloud function

仅支付宝小程序云与腾讯云支持

在支付宝小程序云与腾讯云服务空间的云函数内支持获取同账号下其他服务空间的uniCloud实例,参考:一个应用访问多个服务空间,并使用此实例调用对应服务空间的云函数。

//The developer has created multiple service spaces, which need to be initialized manually. Note that this is the front-end code, not the cloud function code
const myCloud = uniCloud.init({
  provider: 'tencent',
  spaceId: 'xxxx-yyy'
});
//Call the API developed by the cloud through the uniCloud instance
myCloud.callFunction()
myCloud.uploadFile()

Notice

  • When connecting to the local cloud function for debugging, if there is a cross-service space call, the callFunction will use the cloud function

# serverless environment description

Serverless dynamically allocates computing resources, which leads to a number of unique concepts: cold start, instances, concurrent requests, stateless, and pseudo-global variables.

# Cloud function cold start, hot start

Based on the on-demand execution characteristics of cloud functions, when the function is not triggered, computing resources are not activated.

When a cloud function is triggered for the first time, its complete process is as follows:

  1. Serverless instantiate computing instance
  2. Load function code
  3. Start node
  4. Execute the cloud function code

When the function is called, the process of performing these complete steps is called cold start, and the cold start usually takes about one second.

After a cloud function instance is cold-started, the serverless scheduling center will keep the instance for a certain period of time. During the instance reservation period, the client requests the cloud function again, which will not trigger a cold start, and the speed will be faster. Detailed definition of an instance see below

When both the cloud function instance and the execution process are reused, it is called "hot start". The performance of hot start is much better because it has only one step:

  1. Execute the cloud function code

If a cloud function instance has not been called again for a long time, the computing instance will be recycled; when the cloud function is called again later, the cold start of the cloud function will be triggered again.

不同云厂商的函数实例回收时间不同:

  • 支付宝小程序云:60秒
  • Alibaba Cloud: Cloud functions that are not accessed a second time within 15 minutes will be recycled
  • Tencent Cloud: 30 minutes

The intuitive experience is as follows: a cloud function that has not been used for a long time will be slow for the first time, and then accessed immediately for the second time, it will be very fast, with a millisecond-level response.

Note: Although the cold start is slow, it will not exceed 1.5 seconds. If it exceeds 1.5 seconds, there should be a problem with the writing of the cloud function or a problem with the network.

三家云厂商仍然在优化冷启动问题。目前给开发者的建议是:

  1. Using clientDB can reduce the probability of encountering cold start problems
  2. 非高频访问的云函数,合并到高频云函数中。也有的开发者使用单路由方式编写云函数,即在一个云函数中通过路由处理实现了整个应用的所有后台逻辑。参考插件
  3. 非高频访问的云函数,可以通过定时任务持续运行它(注意阿里云公测版的定时任务最短周期大于资源回收周期)
  4. 支付宝小程序云与阿里云支持配置云函数的单实例多并发,请参考:单实例多并发

# Instance and request

Instance refers to an execution environment of cloud functions, which can be simply understood as a node process.

Every time a client initiates a request, the serverless scheduling center will check the started and idle instances and assign an instance to receive the request. If there is no idle instance, a new instance is created.

It takes a certain amount of time to start a new instance, which is the cold start problem mentioned above. See cold start for details

After an instance is started, the request is usually completed within 1 second, but the serverless scheduling center will reserve the instance for a certain period of time (see the previous section for the time). During the instance reservation period, if the client requests the cloud function again, a cold start will not be triggered.

That is to say, during the instance reservation period, 1 instance will accept multiple client requests. **

So be aware that instance and request are not a one-to-one relationship.

Request (request) refers to a network request to connect to a cloud function. Different requests have different context information (such as client UA).

Therefore, if you want to obtain client information, you must pay attention not to obtain it on the global object of the instance, but to obtain it in the context of the request. see details

在uniCloud阿里云版与支付宝小程序版中还提供了1个实例的多并发请求配置,即同一时间多个请求可以并发执行。 That is, when a request is sent to the cloud function at the same time, a new cloud function instance will be opened if the single-instance multi-concurrency is not configured, and a new instance will not be opened if the single-instance multi-concurrency is configured, and the concurrency will be increased in an instance. See Single instance with multiple concurrency for details.

A cloud function can have multiple instances at the same time. For example, if the cf1 cloud function is not configured with multiple concurrent instances, and 10 requests reach the cloud function at the same time, 10 instances will be opened.

No matter how many instances are opened, the billing of the cloud function is billed according to the request. From the time the instance responds to the request to the end of the retention period, if there is no new request, it will not be billed.

# Cloud function's stateless and global variables

Because the instance may be started for the first time, or it may have already been started, the js global variable in the cloud function is actually a pseudo-global variable. That is, cloud functions are stateless.

In cloud objects, variable definitions written before module.exports = {} and cloud functions written before exports.main = async (event, context) => {} are pseudo-global variables.

They are reused across multiple requests over the lifetime of the instance.

Take the following code as an example, count is a global variable, when the cloud function is called multiple times, variables may accumulate.

  • Cloud object example
let count = 0;
module.exports = {
	methoda() {
		return count++
	}
}
  • Cloud function example
let count = 0;
exports.main = async (event, context) => {
	return count++
}

In the above two examples, when the instance is not reused, that is, when the instance is cold started, the value of count is 0 every time; if the instance is reused, it may return 1, 2, 3 and other unexpected situations.

Of course, you can use this method to know how many requests an instance has been reused.

**require also has the same problem due to the existence of cache. Try not to directly modify the content returned by require. **

**The uniCloud global object is also cross-request, and the content related to the request should not be mounted on the uniCloud global object. **

The correct global variable should use the following scheme:

  • uni-config-center: Static global variables can use the configuration center provided by uni. See details
  • redis: Dynamic global variables use redis. See details

# Request context

As mentioned in the previous section, uniCloud global objects are instance-level and cross-request, and uniCloud in an instance will only be initialized once when it is cold started.

So the context related to the request, such as client information, needs to be obtained through the request.

In order for developers to clearly understand the relationship between instances and requests, uniCloud provides the following solutions.

  1. Through uniCloud.getRequestList(), you can get the request id list of the current instance Each request has a requestId, which is reflected in the running callback and cloud logs.
uniCloud.getRequestList()
// Return value: ['3228166e-3c17-4d58-9707-xxxxxxxx']
- If Alibaba Cloud's single-instance multi-concurrency is not configured, there is only one item in the array returned by getRequestList(), that is, only the current request id can be obtained.
- If Alibaba Cloud's single-instance multi-concurrency is configured, when concurrency occurs, this list will return multiple items, and each requestId that is currently concurrent is included.
  1. uniCloud.getClientInfos(), which can return the client information of all current requests. This method returns an array, which contains the client information of each concurrently executing request.
[
  {
    "appId": "__UNI_xxxxx",
    "requestId": "3228166e-3c17-4d58-9707-xxxxxxxx"
    // ...
  }
]
- If Alibaba Cloud's single-instance multi-concurrency is not configured, there is only one item in the array returned by getRequestList(), that is, only the current request id can be obtained.
- If Alibaba Cloud's single-instance multi-concurrency is configured, when concurrency occurs, this list will return multiple items, and each requestId that is currently concurrent is included.

If it is a uniCloud private cloud, If you want to obtain information related to the request, such as the client UA of this request, or cloud function environment information, you cannot directly obtain it from the uniCloud global object.

The entry parameters of the cloud function include an event and a context. These two parameters are related to the request. Every time there is a new request to the cloud function instance, there will be a new event object and a new context object.

The this of cloud objects is similar to event and context, and each request corresponds to a separate this.

# Single instance with multiple concurrency

仅支付宝小程序云与阿里云支持

By default, cloud functions only support single-instance single-concurrency, that is, one instance can only serve one request at a time (different requests at the same time will be assigned to different instances for processing). However, in the uniCloud web console, Alibaba Cloud can modify the maximum number of requests that the cloud function can handle at the same time by modifying the concurrency of a single instance of the cloud function.

Suppose there are 3 requests to be processed at the same time:

When the instance concurrency is set to 1, 3 instances need to be created to handle the 3 requests, and each instance handles 1 request respectively. And every time an instance is opened, it will trigger a cold start of the cloud function;

When the instance concurrency of the cloud function is set to 10 (that is, one instance can handle 10 requests at the same time), only one instance needs to be created to handle the three requests. In this way, the next two concurrent requests will not have the cold start problem caused by the creation of cloud function instances.

Related documents: Cloud function instance and some variable description, Cloud function stateless

Open method

You only need to configure the concurrency of a single instance on the cloud function details page, and the value between 1-100 is supported

Effect

  • Effectively reduce the number of cloud function cold starts during concurrent requests

Usage Caution

  • 虽然支付宝小程序云与阿里云云函数支持配置多并发,但在高并发下异步请求排队效果未必好于新开一个实例。尤其是并发操作数据库性能不佳。一般情况下不要设置过大的并发度,可以自己针对业务代码测试比较下是否启用并发或并发数配成多少
  • The memory usage of cloud functions will increase as the concurrency increases, and excessive memory may lead to OOM
  • Note that cloud functions have timeouts. Setting too large a single instance with multiple concurrency may cause the underlying network requests of the instance to queue up, resulting in request timeouts.
  • If different concurrent requests read and write global variables at the same time, the global variables will be polluted, which may lead to unexpected consequences. For details, see Global Variables

Applicable scene

Scenario Applicability Justification
There is a lot of time in the function waiting for the response from the downstream service Applicable Waiting for the response generally does not consume resources, and concurrent processing in one instance can save costs.
There is a shared state in the function and cannot be accessed concurrently Not applicable For example, global variables, concurrent execution of multiple requests to modify the shared state may cause errors.
The execution of a single request consumes a lot of CPU and memory resources Not applicable Concurrent execution of multiple requests will cause resource contention, which may lead to out-of-memory (OOM) or increased delay.

Special note about the old version of uni-id public module

The old version of uni-id common module refers to the version before uni-id-common was released. See details

// Enable the usage of uni-id before multi-concurrency of single instance
const uniID = require('uni-id')
exports.main = async function(event, context) {
  const res = uniID.login({
    // ...some parameters
  })
  return res
}

// Since uni-id will obtain client platform information from a built-in global variable by default, different requests will modify this global variable, which may cause confusion. After enabling multiple concurrency of a single instance, you need to modify uni-id to the following
let uniID = require('uni-id')
exports.main = async function(event, context) {
  let uniIDIns = uniID.createInstance({ // 创建uni-id实例,其上方法同uniID
    context: context // 传入context防止不同请求互相影响
    // config: {} // Complete uni-id configuration information, no need to pass this parameter when using config.json for configuration
  })
  const res = uniIDIns.login({
    // ...some parameters
  })
  return res
}

Different from the old version of uni-id public module, the new version of uni-id-common cannot be used directly after require, and the createInstance method must be used

Advanced

The reuse of global variables after multiple concurrency of single instance is enabled is not necessarily a bad result. If you understand this behavior well, you can also make effective use of it

Example: ip-filter uses cloud functions to globally cache some ip access information to limit the frequency of single ip access. You can download the sample project to experience it

Affected by the multi-concurrency of a single instance, the global storage of information related to this request by the cloud function will cause confusion. Therefore, uniCloud provides access to client information and cloud information based on the current requestId. Refer to the following documents

# Temporary storage space

Cloud functions are codes that run on the cloud, and the operating environment is elastically deployed by cloud servers, which is very different from traditional Node.js applications.

In other words, the host environment (which can be simply understood as a virtual machine or server hardware) for each execution of a cloud function may be the same or different, so the traditional Node.js development method of storing part of the information on the local hard disk or memory is no longer Suitable.

Therefore, it is not recommended to use node's fs file system related API. It is recommended to replace it with cloud database, cloud storage, and redis solutions.

# Asynchronous behavior in cloud functions

When writing cloud functions, you should pay attention to the use of async and await. nodejs has a built-in module util that can convert functions that conform to error-first form callback into promise form. Details, such as the following example:

const {
	promisify
} = require('util')

let testCallback = {
	value: 'testCallbackValue',
	echo: function(num, callback) {
		setTimeout(() => {
      // The first parameter is error, the second is the return value
			callback(null, `${this.value}:${num}`)
		}, 2000)
	}
}

exports.main = async function() {
  // num=2, do not pass in the callback parameter, the callback will be automatically processed as a callback function
	let val = await promisify(testCallback.echo).call(testCallback, 2)
	console.log(val)
	return val
}

If you want to use the callback form in the cloud function, you can let the cloud function return a promise, as in the following example:

exports.main = async function() {
	return new Promise((resolve, reject) => {
		setTimeout(() => {
			resolve('some return value')
		}, 1000)
	})
}

# return strategy

  • After Alibaba Cloud returns, the cloud function will be terminated immediately, and the logic will not continue to execute, including settimeout or other asynchronous operations will be terminated immediately.
  • Tencent Cloud node8 will not continue to execute after return, but node12 can configure whether to continue to execute
  • HBuilderX running locally
    • Do not initiate through the client, directly run the cloud function/cloud object locally, and can execute 300ms after return
    • Connect to the local cloud function/cloud object through the client, and the execution can continue after return

Because Tencent Cloud bills cloud functions by GBS, especially when using node12, you must pay special attention. If the cloud function is not effectively terminated, it will continue to be billed

# node version

Cloud functions run in the node environment. The node version can be obtained using the node api process.version.

  • uniCloud 支付宝小程序云默认是 node18, 也可以在 package.json 中选择 node16
  • uniCloud Alibaba Cloud is node8.17.0 by default, you can also choose node12 in package.json
  • uniCloud 腾讯云默认是 node8.9.4,也可以在 package.json 中选择 node12
  • HBuilderX 本地运行环境使用的是 HBuilderX 自带的 node 版本,目前为 node16。在 package.json 选择 node版本 只云端生效,且只在第一次上传云函数时生效。

Notice

  • Once the local development uses the dedicated API of node12, you must manually configure and select the operating environment of node12 in package.json when uploading cloud functions. The reason why node12 is not uniformly used by default in the cloud is because the return policy of Tencent Cloud node12 has some special circumstances, see below.
  • The operating environment is set when the cloud function is created on the cloud, and cannot be modified by updating the cloud function. That is, when the cloud function is uploaded for the first time, what is configured in package.json is what it is. If you need to modify the node environment, you need to delete the cloud function first and upload it again.

The node version can be configured in the cloudfunction-config->runtime field of the cloud function's package.json file. For details, refer to: cloud function package.json

# Time zone

The time zone used in cloud functions on the cloud is UTC+0 instead of UTC+8, so special attention should be paid when using time in cloud functions.

When the cloud function is running locally in HBuilderX, the time zone is the time zone of the computer, probably UTC+8. It is recommended to use timestamps uniformly to avoid time zone issues.

# Cloud function configuration

云函数除了代码,还有配置。在uniCloud web控制台可以配置;在HBuilderX项目中,云函数根目录的package.json也是存放配置的地方。

# Running memory

云函数运行内存为单个云函数实例使用的内存。

支付宝小程序云云函数默认运行内存512MB,阿里云正式版默认512MB,腾讯云云函数默认运行内存大小为256MB

计算云函数GBs资源消耗时腾讯云会以此内存*运行时间(100ms为阶梯向上取整)得到消耗量。阿里云会以实际运行时间计算GBs,不会按100ms阶梯向上取整

注意

阿里云一般场景(比如包含数据库访问时)不建议将内存配置为128MB。如果开发起见遇到数据库响应缓慢,在排除索引等因素的影响后可以检查下是不是云函数内存配置为了128MB,如果是建议调整为256MB

# Timeout

支付宝小程序云定时任务触发最大支持3小时超时时间,非定时触发时超时时间为3分钟,客户端请求云函数如果超出3分钟云函数断开连接后会停止运行。

阿里云定时任务触发最大支持600秒超时时间,非定时触发时超时时间为2分钟,客户端请求云函数如果超出60秒云函数断开连接后会停止运行。

腾讯云定时任务触发最大支持900秒超时时间。非定时触发时超时时间为30秒,客户端请求云函数时如果超出30秒云函数断开链接后会继续运行,最大能运行到配置的超时时间。

If the timeout is still not enough, you can refer to the recursive call of cloud functions to execute multiple cloud functions in succession to process a task View details

# Fixed export IP

# Tencent Cloud

Serverless does not have a fixed server IP by default, because there are many server resources in the background for calling at any time, and which server or IP is not fixed each time it is called.

However, some third-party systems require the configuration of a fixed ip whitelist, such as the js sdk of the WeChat public account, which can only provide fixed ip addresses at this time.

The paid version of Tencent Cloud provides a fixed export ip for cloud functions. In uniCloud Web console, create a paid Tencent Cloud service space, select a cloud function, and click On the details interface of the cloud function, you can enable the fixed export ip. After opening, the available fixed IP will be displayed on the interface. Just take this ip to the interface that needs a fixed ip (such as the WeChat official account management interface) to configure.

Notice

  • If you are upgrading from the free version to the paid version, after the fixed IP function is turned on, the paid version will not be automatically downgraded to the free version when it expires, please pay attention to renew on time

The original design of Tencent Cloud is that all cloud functions with fixed egress IPs in the same service space use the same IP. However, the cloud function with vpc enabled cannot share the same egress ip with the function without vpc enabled. The specific use has the following performance

  • Cloud functions with redis extension enabled and cloud functions without redis extension will be assigned different ip
  • If a cloud function has opened a fixed export ip, the fixed ip will change when it is associated with the redis extension library

It is recommended that the redis service space that has been opened should first be associated with the cloud function to redis and then open a fixed export IP. From July 20, 2022, the newly uploaded cloud function will enable the vpc function by default. If you need to keep the old cloud function and the new cloud function It is consistent that you can associate the old cloud function with redis and upload it once. Note that this operation will change the fixed exit IP of the old cloud function

# Aliyun

Added in HBuilderX 3.5.5

uniCloud.httpProxyForEip ,其原理是通过代理请求获得固定出口IP的能力。IP为轮转不固定,因此三方服务要求使用白名单时开发者需要将代理服务器可能的IP均加入到白名单中,见下方代理服务器列表。此外对于代理的域名有限制,当前仅持weixin.qq.com泛域名。若开发者有其他域名代理需求,发送邮件到service@dcloud.io申请,邮件模板参考:申请解除限制邮件模板

代理服务器IP列表

47.92.132.2
47.92.152.34
47.92.87.58
47.92.207.183
8.142.185.204

If you want to use it in the scenario of obtaining the access_token of the WeChat public account, please configure the above ip to WeChat public platform -> Basic configuration -> IP whitelist, related links: [WeChat public platform](https://mp.weixin. qq.com/)

# 支付宝小程序云

暂未支持

# Send Get request

usage

uniCloud.httpProxyForEip.get(url: String, params?: Object)

example

await uniCloud.httpProxyForEip.get(
  'https://api.weixin.qq.com/cgi-bin/token',
  {
    grant_type: 'client_credential', 
    appid: 'xxxx',
    secret: 'xxxx'
  }
)
# Send POST request to carry form data

Note that this interface sends data in application/x-www-form-urlencoded format instead of multipart/form-data

usage

uniCloud.httpProxyForEip.postForm(url: String, data?: Object, headers?: Object)

example

uniCloud.httpProxyForEip.postForm(    
  'https://www.example.com/search',
  {
    q: 'nodejs',
    cat: '1001'
  }
)
# Send POST request with JSON data

post data in application/json format

usage

uniCloud.httpProxyForEip.postJson(url: String, json?: Object, headers?: Object)

example

uniCloud.httpProxyForEip.postJson(    
  'https://www.example.com/search',
  {
    q: 'nodejs',
    cat: '1001'
  }
)
# POST general data

usage

uniCloud.httpProxyForEip.post(url: String, text?: String, headers?: Object)

example

uniCloud.httpProxyForEip.post(    
  'https://www.example.com/search',
  'abcdefg',
  {
    "Content-Type": "text/plain"
  }
)

Notice

  • Does not support sending content in multipart format
  • Proxy request timeout is 5 seconds
  • The above interfaces support local operation

# cloud function package.json

Before HBuilderX version 3.0, package.json was just a standard package.json, which was required only for installing dependencies or public modules. For HBuilderX 3.0 and above, package.json can also be used to configure cloud functions.

The uniCloud web console provides many cloud function settings, such as memory size, urlization, timing trigger, etc. From HBuilderX 3.0 onwards, these settings can also be written in the cloud function's package.json.

Developers write cloud function settings locally and upload cloud functions, and these settings will automatically take effect on the cloud. (Does not work locally)

After setting non-default parameters in the cloud, when HBuilderX downloads the cloud function to the local, it will also automatically put the setting items into package.json and download it.

package.json is a standard json file and cannot be commented. Below is an example package.json.

{
  "name": "add-article",
  "version": "1.0.0",
  "description": "新增文章",
  "main": "index.js",
  "dependencies": {
    // Cloud function dependencies, including public modules and self-installed npm dependencies
  },
	"extensions": {
		// Extended library used by cloud functions
	},
  "cloudfunction-config": {
		"memorySize": 256,
		"timeout": 5,
		"triggers": [{
				"name": "myTrigger",
				"type": "timer",
				"config": "0 0 2 1 * * *"
		}],
		"path": "",
		"runtime": "Nodejs8" 
	}
}

# cloudfunction-config

Among them, the cloudfunction-config field is the cloud function configuration, and the supported configurations are as follows

{
  "concurrency": 10, // 单个云函数实例最大并发量,不配置的情况下默认是1
  "memorySize": 256, // 函数的最大可用内存,单位MB,可选值: 128|256|512|1024|2048,默认值256,阿里云正式版默认512
  "timeout": 5, // 函数的超时时间,单位秒,默认值5。最长为60秒,阿里云在定时触发时最长可以是600秒
  // The triggers field is an array of triggers. Currently, only one trigger is supported, that is, only one array can be filled in, and multiple ones cannot be added
  "triggers": [{ // 阿里云腾讯云均为此形式,请阅读下方说明
      // name: The name of the trigger, see https://uniapp.dcloud.net.cn/uniCloud/trigger for the rules, name does not take effect for Alibaba Cloud
      "name": "myTrigger",
      // type: trigger type, currently only supports timer (i.e. timing trigger), type does not take effect for Alibaba Cloud
      "type": "timer",
      // config: trigger configuration, under the timing trigger, the config format is a cron expression, see https://uniapp.dcloud.net.cn/uniCloud/trigger for the rules. When using Alibaba Cloud, the last digit will be automatically ignored, that is, the digit representing the year will not take effect in Alibaba Cloud
      "config": "0 0 2 1 * * *"
  }],
  // 云函数Url化path部分
  "path": "",
  "runtime": "", // nodejs版本,可选Nodejs8、Nodejs12、Nodejs16、Nodejs18,默认:Nodejs8
  "keepRunningAfterReturn": true // 是否在云函数return之后继续执行,仅腾讯云nodejs12生效,详情见下方说明
}

Nodejs16、Nodejs18 仅支付宝小程序云支持 When using Tencent Cloud Nodejs12 version, be sure to read this document carefully: keepRunningAfterReturn

# Timing task triggers

支付宝小程序云与阿里云定时触发的cron表达式不支持代表年的第七位,但是在package.json内配置时仍需将第七位设置为*。

Please refer to:Tiger Trigger to configure the trigger on the web console.**

package.json内统一了支付宝小程序云、腾讯云、阿里云三家厂商的配置,三个平台都需要配置为如下形式

{
	"name": "myTrigger",
	"type": "timer",
	"config": "0 0 2 1 * * *"
}

# keepRunningAfterReturn

Added in HBuilderX 3.5.1

Alibaba Cloud and Tencent Cloud nodejs8 will freeze the rest of the logic after the cloud function returns. The behavior of Tencent Cloud nodejs12 is just the opposite. After the cloud function returns, it will wait for the rest of the logic to be executed before the cloud function instance will be free.

Take the following code as an example

exports.main = async function(event, context) {
	setTimeout(()=>{
	  console.log('delay 5 seconds')
	}, 5000)
	return {}
}

If the cloud function runs on Alibaba Cloud or Tencent Cloud nodejs8, the console.log in setTimeout will not be executed when the cloud function is called, but may continue to execute when the cloud function instance is reused again.

If this cloud function runs on Tencent Cloud nodejs12, the console.log in setTimeout will be included in this cloud function call, and the same cloud function billing time (related to the cloud function GBs indicator) will also be calculated according to the final Completion time calculation (5000ms+return time-consuming). But the frontend doesn't need to wait 5 seconds for the response. Note: If there is a long connection (for example: redis connection) that has not been disconnected, it will cause the cloud function to run until the configured timeout period

When keepRunningAfterReturn: false is configured in the cloudfunction-config in the cloud function package.json, the performance of Tencent Cloud nodejs12 can be changed, and the execution of the cloud function will not continue after the return, and the undisconnected long connection will not increase The actual running time of the cloud function, and the long connection will not be interrupted after the cloud function returns. Simply put, its performance is consistent with Tencent Cloud nodejs8.

Send network request in cloud function

Replace the setTimeout in the above example with a network request, and call other cloud functions or database requests. In the same way, if you return directly on Alibaba Cloud or Tencent Cloud nodejs8, the network request may not be sent (even if it is successfully sent, it will be the next time the cloud function instance is resumed. When used), this is different from traditional development.

exports.main = async function(event, context) {
	uniCloud.callFunction({ 
    name: 'test',
    data: {}
  })
	return {} // callFunction后不等待直接return时无法调用到test云函数
}

Tencent cloud nodejs12 uses redis

Since redis needs to establish a connection with the server, this connection will prevent the cloud function from finishing execution. If there is no need to continue execution after the cloud function returns, you can simply configure keepRunningAfterReturn: false in cloudfunction-config. In this way, the redis connection will not be interrupted, and the previously established connection can still be used when the next request comes.

If you need to continue execution after return, you need to disconnect the redis connection after use, and call the redis.quit() method to disconnect. It should be noted that after the connection is disconnected, the previously established connection will no longer be available, and the uniCloud.redis() method needs to be used to re-establish the connection when the next request comes.

If the above instructions are not followed, the redis connection will always occupy the cloud function instance, causing the cloud provider to continuously calculate the execution time of the cloud function, which may result in the consumption of a large amount of cloud resources and additional costs

Be sure to make sure that you have understood the content of this document, and DCloud will not be responsible for any additional billing caused by failure to follow the instructions in the document

# Precautions

  • When the plug-in author releases the plug-in, if the cloud function has special settings, it should be put into package.json and then published to the plug-in market. In this way, there is no need to guide users step by step through the documentation to configure cloud function timing triggers, memory, urlization paths, etc.
  • After modifying the cloud function configuration in the web console, the modified cloud function configuration will be added to package.json through the download cloud function menu of HBuilderX
  • When uploading the cloud function, if the package.json under the project contains the cloud function configuration, the cloud function configuration will be updated at the same time
  • package.json is valid only for cloud deployment, not for local operation.
  • cloudfunction-config cannot delete the cloud configuration. Example: triggers (timing triggers) have been configured in the cloud, deleting the trigger in cloudfunction-config will not delete the timing triggers in the cloud
  • The runtime parameter (nodejs version) can only take effect when creating a cloud function and cannot be modified

# The number, volume, and cold start balance of cloud functions

鉴于:

  • 每个服务空间的云函数数量是有限的,支付宝小程序云是499个,阿里云是48个,腾讯云是149个,详见
  • The volume limit of each cloud function is 10M (including node_modules)
  • Cloud function has cold start problem

Based on the above situation, the following suggestions are made for the development model:

  1. It is generally not recommended to use node_modules with large size and deep dependencies. Use more libraries provided by DCloud official or plug-in market.
  2. Prioritize the use of clientDB, which does not occupy the number of cloud functions and does not need to write server code.
  3. Properly merge and disassemble cloud objects or cloud functions.
    • It is not recommended to use cloud functions independently for operations that are low-frequency and have a great impact on user experience, and are merged into high-frequency cloud functions.
    • Control the volume of a single cloud function. Some developers like to use [single route cloud function](https://ext.dcloud.net.cn/search?q=%E8%B7%AF%E7%94%B1&orderBy= WeekDownload&cat1=7), the entire service space is a cloud function. This also depends on the actual situation. If the volume of the cloud function exceeds 6M, it is still recommended to split it.
    • In terms of user system, the official uni-id-co cloud object has been provided, and with clientDB, conventional business is enough. If there are special needs, some cloud objects can be added moderately. It is unlikely that the number of cloud functions will be insufficient.
  4. Multiple service spaces can be used when necessary, and can be used across service spaces

# cloudfunctions_init (deprecated)

HBuilderX 2.9 version, uniCloud provides cloudfunctions_init.json to facilitate developers to quickly initialize cloud functions.

Note: HBuilderX version 3.0.0 no longer uses cloudfunctions_init.json to initialize cloud functions. Instead, configure it through package.json in the cloud function directory, see the previous chapter for details

The detailed adjustments are as follows:

Cloudfunctions_init.json is no longer used, and the content is distributed to the cloudfunction-config field of each cloud function's package.json

package.json is a standard json file and cannot be commented. Below is an example package.json

{
  "name": "add-article",
  "version": "1.0.0",
  "description": "新增文章",
  "main": "index.js",
  "dependencies": {
    
  },
  "cloudfunction-config": {
      "memorySize": 256,
      "timeout": 5,
      "triggers": [{
          "name": "myTrigger",
          "type": "timer",
          "config": "0 0 2 1 * * *"
      }],
      "path": ""
    }
}

The description of cloudfunction-config is as follows

{
  "memorySize": 256, // 函数的最大可用内存,单位MB,可选值: 128|256|512|1024|2048,默认值256,阿里云正式版默认512
  "timeout": 5, // 函数的超时时间,单位秒,默认值5。最长为60秒,阿里云在定时触发时最长可以是600秒
  // The triggers field is an array of triggers. Currently, only one trigger is supported, that is, only one array can be filled in, and multiple ones cannot be added
  "triggers": [{
      // name: The name of the trigger, see https://uniapp.dcloud.net.cn/uniCloud/trigger for the rules, name does not take effect for Alibaba Cloud
      "name": "myTrigger",
      // type: trigger type, currently only supports timer (i.e. timing trigger), type does not take effect for Alibaba Cloud
      "type": "timer",
      // config: trigger configuration, under the timing trigger, the config format is a cron expression, see https://uniapp.dcloud.net.cn/uniCloud/trigger for the rules. When using Alibaba Cloud, the last digit will be automatically ignored, that is, the digit representing the year will not take effect in Alibaba Cloud
      "config": "0 0 2 1 * * *"
  }],
  // 云函数Url化path部分
  "path": ""
}

For versions before HBuilderX 3.0.0, please continue to read the following documents

How to use

  • Right click on the cloudfucntions directory to create cloudfunctions_init.json,
  • After writing the json content, right-click on cloudfunctions_init.json to initialize the cloud function configuration.

cloudfunctions_init.json format is as follows

{
    "fun-name": { // 云函数名称
        "memorySize": 256, // 函数的最大可用内存,单位MB,可选值: 128|256|512|1024|2048,默认值256,阿里云正式版默认512
        "timeout": 5, // 函数的超时时间,单位秒,默认值5。
        // The triggers field is an array of triggers. Currently, only one trigger is supported, that is, only one array can be filled in, and multiple ones cannot be added
        "triggers": [{
            // name: The name of the trigger, see https://uniapp.dcloud.net.cn/uniCloud/trigger for the rules, name does not take effect for Alibaba Cloud
            "name": "myTrigger",
            // type: trigger type, currently only supports timer (i.e. timing trigger), type does not take effect for Alibaba Cloud
            "type": "timer",
            // config: trigger configuration, under the timing trigger, the config format is a cron expression, see https://uniapp.dcloud.net.cn/uniCloud/trigger for the rules. When using Alibaba Cloud, the last digit will be automatically ignored, that is, the digit representing the year will not take effect in Alibaba Cloud
            "config": "0 0 2 1 * * *"
        }],
        // 云函数Url化path部分
        "path": ""
    }
}

On This Page