小程序开放平台

文档中心
如何编写云函数

如何编写云函数

开发指南
>
云函数开发
>
如何编写云函数
>
更新时间:2025-12-19 16:18:41

函数入参详解

每个云函数调用都会收到两个重要对象:

event
context

event 对象

event
对象包含触发云函数的事件数据,其内容根据触发方式不同而变化:

  • HTTP 请求调用:包含 HTTP 请求信息(如请求头、请求体等)
    • JSON 请求:
      event
      直接包含解析后的 JSON 对象
    • Form-data 请求:
      event
      包含表单字段

context 对象

context
对象提供调用上下文信息,帮助您了解函数的运行环境和调用方式:

  • eventID:当前调用的唯一标识符,可用于日志追踪和错误排查
  • eventType:事件类型(如 "http")
  • timestamp:请求时间戳(ISO 8601 格式的 UTC 时间字符串)
  • httpContext:HTTP 请求上下文信息(包含 URL、HTTP 方法、请求头等)
  • request:内置的 HTTP 请求工具类,支持 get、post、put、upload、download 等方法
  • logger:日志记录工具,用于记录访问日志和用户代码日志

基础代码示例

以下是一个简单的 Node.js 云函数示例,展示如何处理入参并返回结果:

javascript
// index.js - 云函数入口文件
exports.main = async (event, context) => {
  // 1. 解析云函数入参
  const { a, b } = event;

  // 2. 执行业务逻辑
  const sum = a + b;

  // 3. 返回结果
  return {
    sum,
    timestamp: Date.now(),
    requestId: context.eventID,
  };
};

异步处理实践

由于实例的管理由平台自动处理,推荐云函数采用 async/await 模式,避免使用 Promise 链式调用:

javascript
exports.main = async (event, context) => {
  // ❌ 不推荐:Promise 链式调用
  getList().then((res) => {
    // do something...
  });

  // ✅ 推荐:使用 async/await
  const res = await getList();
  // do something...
};

环境变量使用

云函数可以通过

process.env
获取环境变量,这是管理配置信息的实践。

框架支持自动加载

.env
文件,支持按环境加载不同的配置文件。

获取环境变量

javascript
exports.main = async (event, context) => {
  // 获取环境变量
  const dbUrl = process.env.DATABASE_URL;
  const apiKey = process.env.API_KEY;
  const nodeEnv = process.env.NODE_ENV || 'development';

  // 使用环境变量进行配置
  const config = {
    database: dbUrl,
    apiKey: apiKey,
    debug: nodeEnv === 'development',
  };

  return {
    message: '环境变量获取成功',
    environment: nodeEnv,
  };
};

环境变量实践

javascript
exports.main = async (event, context) => {
  // 检查必需的环境变量
  const requiredEnvVars = ['DATABASE_URL', 'API_KEY'];
  const missingVars = requiredEnvVars.filter((varName) => !process.env[varName]);

  if (missingVars.length > 0) {
    throw new Error(`缺少必需的环境变量: ${missingVars.join(', ')}`);
  }

  // 安全地使用环境变量
  const config = {
    dbUrl: process.env.DATABASE_URL,
    apiKey: process.env.API_KEY,
    timeout: parseInt(process.env.TIMEOUT) || 5000,
  };

  return { success: true, config };
};

使用 ES Module 规范

在云函数 Node.js 环境中,默认支持的入口文件(

index.js
)必须遵循 CommonJS 规范。如果需要在云函数中使用 ES Module,可以通过动态导入的方式实现。

项目结构

cloud-function/
├── index.js        # 云函数入口文件(CommonJS)
├── entry.mjs       # ES Module 入口文件
└── src
    └── util.mjs       # 业务逻辑模块,命名可自定义

1. 创建云函数入口文件 index.js

javascript
// index.js - 云函数入口文件
exports.main = async (event, context) => {
  try {
    // 动态导入 ES Module 入口文件
    const { entry } = await import('./entry.mjs');
    return await entry(event, context);
  } catch (error) {
    console.error('云函数执行失败:', error);
    return {
      success: false,
      error: error.message,
      requestId: context.eventID,
    };
  }
};

2. 创建 ES Module 入口文件 entry.mjs

javascript
// entry.mjs - ES Module 入口文件
import { getUserList } from './src/util.mjs';

/**
 * ES Module 入口函数
 * @param {Object} event - 事件对象
 * @param {Object} context - 上下文对象
 * @returns {Promise<Object>} 处理结果
 */
export const entry = async (event, context) => {
  return getUserList(event, context);
};

3. 创建业务逻辑模块 util.mjs

javascript
// src/util.mjs - 业务逻辑模块
export const getUserList = async (event) => {
  // 业务逻辑处理
  return {
    success: true,
    data: [],
  };
};

错误处理与日志记录

错误处理实践

javascript
exports.main = async (event, context) => {
  try {
    // 参数验证
    if (!event.userId) {
      throw new Error('缺少必需参数: userId');
    }

    // 业务逻辑处理
    const result = await processUserData(event.userId);

    return {
      success: true,
      data: result,
    };
  } catch (error) {
    // 记录错误日志
    context.logger.logError(error, {
      event,
      requestId: context.eventID,
    });

    // 返回友好的错误信息
    return {
      success: false,
      error: error.message,
      requestId: context.eventID,
    };
  }
};

日志记录实践

框架提供了内置的日志工具

context.logger
,支持两种日志类型:

  • ACCESS 日志:记录 HTTP 访问日志
  • USERCODE 日志:记录用户代码中的日志输出
javascript
exports.main = async (event, context) => {
  // 记录访问日志
  // 注意:logAccesslog 的第一个参数是 LogLevel 枚举值('info'、'warn'、'error'、'debug')
  context.logger.logAccesslog('info', '处理用户请求', {
    userId: event.userId,
    action: 'getUserInfo',
  });

  // 使用 console 输出会自动记录为用户代码日志
  console.log('开始处理业务逻辑');
  console.info('用户ID:', event.userId);
  console.warn('这是一个警告');
  console.error('这是一个错误');

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

性能优化建议

执行时间优化

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

  try {
    // 使用并行处理提升性能
    const promises = event.items.map((item) => processItem(item));
    const results = await Promise.all(promises);

    const duration = Date.now() - startTime;
    console.log(`函数执行耗时: ${duration}ms`);

    return {
      success: true,
      data: results,
      duration,
    };
  } catch (error) {
    console.error('执行错误:', error);
    throw error;
  }
};

内存使用优化

javascript
exports.main = async (event, context) => {
  // 分批处理大数据,避免内存溢出
  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);

    // 及时清理不需要的变量
    batch.length = 0;

    // 记录处理进度
    console.log(`已处理 ${Math.min(i + batchSize, event.data.length)}/${event.data.length} 条数据`);
  }

  return results;
};

HTTP 请求工具

框架提供了内置的 HTTP 请求工具

context.request
,支持多种请求方法:

javascript
exports.main = async (event, context) => {
  // GET 请求
  const getResponse = await context.request.get({
    url: 'https://api.example.com/data',
    headers: {
      Authorization: 'Bearer token',
    },
  });

  // POST 请求
  const postResponse = await context.request.post({
    url: 'https://api.example.com/data',
    data: {
      name: 'test',
      value: 123,
    },
  });

  // 文件上传
  const uploadResponse = await context.request.upload({
    url: 'https://api.example.com/upload',
    file: event.file.buffer, // 文件 Buffer
    name: 'file.jpg',
    data: {
      folder: 'images',
    },
  });

  // 文件下载
  const downloadResponse = await context.request.download({
    url: 'https://api.example.com/file.pdf',
  });

  return {
    getData: getResponse.data,
    postData: postResponse.data,
    uploadResult: uploadResponse.data,
    downloadData: downloadResponse.data,
    downloadUrl: downloadResponse.tempFilePath,
  };
};