Skip to main content

Writing a Cloud Function

Deep Dive into Function Input Parameters

Each cloud function call receives two important objects: event and context.

The event Object

The event object contains the event data that triggers the cloud function, the content of which varies depending on the trigger method:

  • Mini-program Invocation: contains parameters passed from the mini-program side
  • HTTP Request Invocation: contains HTTP request information (such as headers, body, etc.)
  • Timer Trigger: contains relevant information about the timer trigger

The context Object

The context object provides invocation context information, which helps you understand the runtime environment and invocation method of the function:

  • Request ID: the unique identifier for the current invocation
  • Source of the Invocation: information about the service or client that triggered the function
  • Execution Environment: runtime information of the function
  • User Identity: identity information of the caller (if available)

Basic Code Example

Here is a simple Node.js cloud function example demonstrating how to process input parameters and return results:

// index.js - cloud function entry file
exports.main = async (event, context) => {
// 1. Parse cloud function input parameters
const { a, b } = event;

// 2. Execute business logic
const sum = a + b;

// 3. Return the result
return {
sum,
timestamp: Date.now(),
requestId: context.requestId,
};
};

Asynchronous Processing Practices

Since instance management is automatically handled by the platform, it is recommended to use the async/await pattern for cloud functions instead of Promise chaining:

exports.main = async (event, context) => {
// ❌ Not recommended: Promise chaining
getList().then((res) => {
// do something...
});

// ✅ Recommended: Use async/await
const res = await getList();
// do something...
};

Installing Third-party Dependencies

When a cloud function requires the use of third-party npm packages, the corresponding dependencies must be installed first. The CloudBase online editor provides a convenient dependency management feature.

Open the terminal

In the CloudBase online editor, you can open the terminal in the following ways:

  • Keyboard shortcuts: Use Ctrl + J (Windows/Linux) or command + J (macOS)
  • Menu operations: Click the "Terminal" button above the editor, select "New Terminal"

Install Dependencies

Use the npm add command in the terminal to install the required dependency packages.

Take the installation of the CloudBase Node.js SDK as an example:

npm add @cloudbase/node-sdk

Install other common dependency packages:

# Timezone Handling Library
npm add moment-timezone

# HTTP Request Library
npm add axios

# Tool Library
npm add lodash

Using Dependencies

After installation, you can reference these dependencies in your code:

In the cloud function Node.js environment, code cannot be written directly using the ES Module specification. The main reason is that the entry file (index.js) supported by cloud functions by default must follow the CommonJS specification. To use the ES Module specification, see using-es-module-specification

const cloudbase = require('@cloudbase/node-sdk');

exports.main = async (event, context) => {
// Initialize CloudBase
const app = cloudbase.init({
env: 'your-envid', // Replace with your environment ID
});

const db = app.database();
const collection = db.collection('users');

// Query data.
const { data } = await collection.get();

return {
success: true,
count: data.length,
};
};

Upload and Deployment

After writing code and installing dependencies, select the appropriate upload method based on your project needs:

  • With third-party dependencies: click the Save and Install Dependencies button
    • The system will automatically upload code files and package.json
    • Automatically execute npm install to install dependencies in the cloud environment
    • Ensure that the cloud function can correctly load all dependency packages during runtime
  • Without third-party dependencies: click the Save button
    • Only upload code files
    • Applicable to cloud functions that do not use third-party dependencies
Dependency Management Tips
  • Avoid installing excessive unnecessary dependencies to reduce the function package size and startup time

Environment Variable Usage

Cloud functions can obtain environment variables via process.env, which is a practice for managing configuration information:

Obtaining Environment Variables

exports.main = async (event, context) => {
// Obtaining Environment Variables
const dbUrl = process.env.DATABASE_URL;
const apiKey = process.env.API_KEY;
const nodeEnv = process.env.NODE_ENV || 'development';

// Use environment variables for configuration
const config = {
database: dbUrl,
apiKey: apiKey,
debug: nodeEnv === 'development',
};

return {
message: 'Environment variables successfully obtained',
environment: nodeEnv,
};
};

Environment Variable Practices

exports.main = async (event, context) => {
// Check required environment variables
const requiredEnvVars = ['DATABASE_URL', 'API_KEY'];
const missingVars = requiredEnvVars.filter((varName) => !process.env[varName]);

if (missingVars.length > 0) {
throw new Error(`Missing required environment variables: ${missingVars.join(', ')}`);
}

// Securely use environment variables
const config = {
dbUrl: process.env.DATABASE_URL,
apiKey: process.env.API_KEY,
timeout: parseInt(process.env.TIMEOUT) || 5000,
};

return { success: true, config };
};
Note

Sensitive information (such as API keys, database connection strings) should be passed via environment variables and should not be hard-coded in the code.

  • Environment variable values are always of string type; convert them as needed.
  • Set default values for environment variables to enhance code robustness.

Timezone Settings

The runtime environment of cloud functions maintains UTC time, which is UTC+0, and has an 8-hour difference from Beijing time.

You can use language-specific time processing libraries or packages (such as moment-timezone) to recognize UTC time and convert it to UTC+8 (Beijing Time).

Timezone Handling Example

const moment = require('moment-timezone'); // This needs to be specified and installed in package.json

exports.main = async (event, context) => {
// javascript date
console.log(new Date()); // 2021-03-16T08:04:07.441Z (UTC+0)
console.log(moment().tz('Asia/Shanghai').format()); // 2021-03-16T16:04:07+08:00 (UTC+8)

// Get current Beijing time
const beijingTime = moment().tz('Asia/Shanghai');

return {
utcTime: new Date().toISOString(),
beijingTime: beijingTime.format(),
timestamp: beijingTime.valueOf(),
};
};

Timezone Handling Practices

const moment = require('moment-timezone');

exports.main = async (event, context) => {
// Unified Timezone Handling Function
const getBeijingTime = (date = new Date()) => {
return moment(date).tz('Asia/Shanghai');
};

// Format time output
const formatTime = (date, format = 'YYYY-MM-DD HH:mm:ss') => {
return getBeijingTime(date).format(format);
};

// Used in business logic
const currentTime = getBeijingTime();
const formattedTime = formatTime();

console.log('Current Beijing time:', formattedTime);

return {
success: true,
currentTime: formattedTime,
timestamp: currentTime.valueOf(),
};
};

Using ES Module Specification

In the Node.js environment of cloud functions, it is not possible to directly use the ES Module specification to write code. The main reason is that the default entry file supported by cloud functions (index.js) must follow the CommonJS specification, and the file name must be 'index.js'. However, Node.js requires that module files conforming to the ES Module specification have the extension .mjs.

Using ES Module in cloud functions requires creating three core files to form a complete invocation chain: index.jsentry.mjsutil.mjs

Project Structure

cloud-function/
├── index.js # cloud function entry file (CommonJS)
├── entry.mjs # ES Module entry file
└── src
└── util.mjs # business logic module, the name can be customized

1. Create the cloud function entry file index.js

// index.js - cloud function entry file
exports.main = async (event, context) => {
try {
// Dynamically import the ES Module entry file
const { entry } = await import('./entry.mjs');
return await entry(event, context);
} catch (error) {
console.error('Cloud function execution failed:', error);
return {
success: false,
error: error.message,
requestId: context.request_id
};
}
};

2. Create the ES Module entry file entry.mjs

// entry.mjs - ES Module entry file
import { getUserList } from './src/util.mjs';

/**
* ES Module entry function
* @param {Object} event - The event object
* @param {Object} context - The context object
* @returns {Promise<Object>} Processing result
*/
export const entry = async (event, context) => {
return getUserList(event, context);
};

3. Create the business logic module util.mjs

// src/util.mjs - business logic module
import cloudbase from '@cloudbase/node-sdk';

const app = cloudbase.init({
env: 'your-envid', // Replace with your environment ID
});

const models = app.models;

export const getUserList = async (event) => {
const res = await models.user.list({});

return {
success: true,
data: res,
};
};

💡 Note: ES Module files must use the .mjs extension so that Node.js can correctly identify and process ES Module syntax.

Error Handling and Logging

Error Handling Practices

exports.main = async (event, context) => {
try {
// Parameter validation
if (!event.userId) {
throw new Error('Missing required parameter: userId');
}

// Business logic processing
const result = await processUserData(event.userId);

return {
success: true,
data: result,
};
} catch (error) {
// Log error
console.error('Function execution failed:', {
error: error.message,
stack: error.stack,
event,
requestId: context.requestId,
});

// Return user-friendly error messages
return {
success: false,
error: error.message,
requestId: context.requestId,
};
}
};

Performance Optimization Recommendations

Execution Time Optimization

exports.main = async (event, context) => {
const startTime = Date.now();

try {
// Use parallel processing to improve performance
const promises = event.items.map((item) => processItem(item));
const results = await Promise.all(promises);

const duration = Date.now() - startTime;
console.log(`Function execution time: ${duration}ms`);

return {
success: true,
data: results,
duration,
};
} catch (error) {
console.error('Execution error:', error);
throw error;
}
};

Memory Usage Optimization

exports.main = async (event, context) => {
// Process large data in batches to avoid memory overflow
const batchSize = parseInt(process.env.BATCH_SIZE) || 100;
const results = [];

for (let i = 0; i < event.data.length; i += batchSize) {
const batch = event.data.slice(i, i + batchSize);
const batchResult = await processBatch(batch);
results.push(...batchResult);

// Clean up unused variables promptly
batch.length = 0;

// Log processing progress
console.log(`Processed ${Math.min(i + batchSize, event.data.length)}/${event.data.length} records`);
}

return results;
};