uniCloud 云函数与云对象的异同

144 阅读9分钟

1.3 云函数与云对象的异同

1. 基本概念对比

云函数(Cloud Function)

云函数是 uniCloud 提供的一种服务端函数,它允许开发者在云端执行代码,处理业务逻辑,并返回结果给客户端。云函数是一种函数式的编程模式,每个云函数都是一个独立的函数,通过 callFunction 方法调用。

云对象(Cloud Object)

云对象是 uniCloud 提供的一种新的服务端开发模式,它允许开发者以面向对象的方式编写服务端代码,并在客户端直接调用这些对象的方法。云对象是一种面向对象的编程模式,每个云对象包含多个方法,客户端可以直接调用这些方法。

2. 文件结构对比

云函数的文件结构

一个典型的云函数包含以下文件:

  1. index.js:云函数的主入口文件,包含云函数的实现代码。
  2. package.json:云函数的配置文件,包含依赖项、版本号等信息。
  3. node_modules:云函数的依赖包目录。

云对象的文件结构

一个典型的云对象包含以下文件:

  1. index.obj.js:云对象的主入口文件,包含云对象的实现代码。
  2. package.json:云对象的配置文件,包含依赖项、版本号等信息。
  3. node_modules:云对象的依赖包目录。

3. 代码组织方式对比

云函数的代码组织

云函数通常使用 switch-caseif-else 结构来组织不同的功能:

// 云函数名:todo
'use strict';
exports.main = async (event, context) => {
  const { method, params } = event;
  
  switch (method) {
    case 'add': {
      let { title, content } = params;
      title = title.trim();
      content = content.trim();
      if (!title || !content) {
        return {
          errCode: 'INVALID_TODO',
          errMsg: 'TODO标题或内容不可为空'
        };
      }
      // ...其他逻辑
      return {
        errCode: 0,
        errMsg: '创建成功'
      };
    }
    case 'getList': {
      // 获取列表逻辑
      return {
        errCode: 0,
        errMsg: '获取成功',
        data: []
      };
    }
    // 其他方法
    default: {
      return {
        errCode: 'METHOD_NOT_FOUND',
        errMsg: `Method[${method}] not found`
      };
    }
  }
};

云对象的代码组织

云对象使用面向对象的方式组织代码,每个方法都是对象的一个属性:

// 云对象名:todo
module.exports = {
  // 添加待办事项
  async add(title, content) {
    title = title.trim();
    content = content.trim();
    if (!title || !content) {
      return {
        errCode: 'INVALID_TODO',
        errMsg: 'TODO标题或内容不可为空'
      };
    }
    // ...其他逻辑
    return {
      errCode: 0,
      errMsg: '创建成功'
    };
  },
  
  // 获取待办事项列表
  async getList() {
    // 获取列表逻辑
    return {
      errCode: 0,
      errMsg: '获取成功',
      data: []
    };
  }
};

4. 调用方式对比

云函数的调用方式

客户端调用云函数需要使用 uniCloud.callFunction 方法,并传递方法名和参数:

// 调用云函数
uniCloud.callFunction({
  name: 'todo',
  data: {
    method: 'add',
    params: {
      title: '标题',
      content: '内容'
    }
  }
}).then(res => {
  const { errCode, errMsg } = res.result;
  if (errCode === 0) {
    uni.showToast({
      title: '创建成功'
    });
  } else {
    uni.showModal({
      title: '创建失败',
      content: errMsg,
      showCancel: false
    });
  }
}).catch(err => {
  uni.showModal({
    title: '创建失败',
    content: err.errMsg,
    showCancel: false
  });
});

云对象的调用方式

客户端调用云对象需要使用 uniCloud.importObject 方法导入云对象,然后直接调用对象的方法:

// 导入云对象
const todo = uniCloud.importObject('todo');

// 调用云对象方法
async function addTodo() {
  try {
    const result = await todo.add('标题', '内容');
    if (result.errCode === 0) {
      uni.showToast({
        title: '创建成功'
      });
    } else {
      uni.showModal({
        title: '创建失败',
        content: result.errMsg,
        showCancel: false
      });
    }
  } catch (e) {
    uni.showModal({
      title: '创建失败',
      content: e.errMsg,
      showCancel: false
    });
  }
}

5. 特殊方法对比

云函数的特殊方法

云函数没有特殊的生命周期方法,所有逻辑都在 main 函数中处理。

云对象的特殊方法

云对象支持一些特殊的方法,这些方法以 _ 开头,用于处理云对象的生命周期和通用逻辑:

  1. _before:在调用云对象方法前执行,用于预处理,如参数验证、权限检查等。
  2. _after:在调用云对象方法后执行,用于后处理,如日志记录、结果转换等。
  3. _timing:定时执行的方法,用于定时任务。
// 云对象名:todo
module.exports = {
  // 预处理方法
  async _before() {
    // 获取客户端信息
    const clientInfo = this.getClientInfo();
    console.log('客户端信息', clientInfo);
    
    // 获取客户端 token
    const token = this.getClientToken();
    console.log('客户端 token', token);
  },
  
  // 后处理方法
  async _after(result) {
    // 记录日志
    console.log('方法执行结果', result);
    
    // 返回结果
    return result;
  },
  
  // 定时执行的方法
  async _timing() {
    console.log('定时任务执行', new Date().toISOString());
    // 执行定时任务
    return {
      errCode: 0,
      errMsg: '定时任务执行成功'
    };
  },
  
  // 其他方法
};

6. 交互界面对比

云函数的交互界面

云函数调用不会自动显示交互界面,需要开发者手动处理加载提示和错误处理:

// 显示加载提示
uni.showLoading({
  title: '加载中...'
});

// 调用云函数
uniCloud.callFunction({
  name: 'todo',
  data: {
    method: 'add',
    params: {
      title: '标题',
      content: '内容'
    }
  }
}).then(res => {
  // 隐藏加载提示
  uni.hideLoading();
  
  const { errCode, errMsg } = res.result;
  if (errCode === 0) {
    uni.showToast({
      title: '创建成功'
    });
  } else {
    uni.showModal({
      title: '创建失败',
      content: errMsg,
      showCancel: false
    });
  }
}).catch(err => {
  // 隐藏加载提示
  uni.hideLoading();
  
  uni.showModal({
    title: '创建失败',
    content: err.errMsg,
    showCancel: false
  });
});

云对象的交互界面

云对象调用默认会自动显示交互界面,包括加载提示和错误处理:

// 导入云对象
const todo = uniCloud.importObject('todo');

// 调用云对象方法,自动显示加载提示和错误处理
async function addTodo() {
  try {
    const result = await todo.add('标题', '内容');
    if (result.errCode === 0) {
      uni.showToast({
        title: '创建成功'
      });
    }
  } catch (e) {
    // 错误处理由云对象自动完成
  }
}

如果需要自定义交互界面,可以在导入云对象时传入配置:

// 导入云对象,自定义交互界面
const todo = uniCloud.importObject('todo', {
  customUI: false, // 是否取消自动展示的交互提示界面,默认为 false
  loadingOptions: { // loading 相关配置
    title: '加载中...', // 显示的 loading 内的提示文字
    mask: true // 是否使用透明遮罩,配置为 true 时不可点击页面其他内容
  },
  errorOptions: { // 错误界面相关配置
    type: 'modal', // 错误信息展示方式,可取值:modal(弹框)、toast(toast 消息框)
    retry: false // 是否展示重试按钮,仅在 type 为 modal 时生效
  }
});

7. 类型提示对比

云函数的类型提示

云函数不支持 JSDoc 注释,无法提供类型提示。

云对象的类型提示

云对象支持 JSDoc 注释,可以提供更好的代码提示和类型检查:

// 云对象名:todo
module.exports = {
  /**
   * 添加待办事项
   * @param {string} title 待办事项标题
   * @param {string} content 待办事项内容
   * @returns {object} 返回结果
   */
  async add(title, content) {
    // 方法实现
  },
  
  /**
   * 获取待办事项列表
   * @returns {object} 返回结果
   */
  async getList() {
    // 方法实现
  }
};

8. 适用场景对比

云函数的适用场景

  1. 简单的业务逻辑:适用于简单的业务逻辑,如数据查询、简单的数据处理等。
  2. 传统的函数式编程:适用于喜欢函数式编程风格的开发者。
  3. 需要兼容旧版本:适用于需要兼容旧版本的场景。

云对象的适用场景

  1. 复杂的业务逻辑:适用于复杂的业务逻辑,如用户管理、订单处理等。
  2. 面向对象编程:适用于喜欢面向对象编程风格的开发者。
  3. 需要更好的代码组织:适用于需要更好的代码组织的场景。
  4. 需要更好的类型支持:适用于需要更好的类型支持的场景。
  5. 需要更好的错误处理:适用于需要更好的错误处理的场景。
  6. 需要更好的用户体验:适用于需要更好的用户体验的场景。

9. 性能对比

云函数的性能

云函数的性能取决于函数的复杂度和执行时间。由于云函数是独立的函数,每次调用都需要重新初始化,可能会有一定的冷启动时间。

云对象的性能

云对象的性能也取决于对象的复杂度和执行时间。由于云对象是面向对象的方式,可能会有更好的代码复用和缓存效果,但也可能会有更多的内存占用。

10. 开发效率对比

云函数的开发效率

云函数的开发效率相对较低,因为需要手动处理参数传递、错误处理、交互界面等。

云对象的开发效率

云对象的开发效率相对较高,因为:

  1. 代码更简洁:减少了样板代码,使开发更加高效。
  2. 更好的代码组织:面向对象的方式使代码结构更清晰,更易于维护。
  3. 更好的类型支持:通过 JSDoc 注释提供更好的类型提示和检查。
  4. 更好的错误处理:统一的错误处理机制,减少重复代码。
  5. 更好的用户体验:默认提供加载提示和错误处理,提升用户体验。

11. 最佳实践建议

何时使用云函数

  1. 简单的业务逻辑:当业务逻辑简单,不需要复杂的代码组织时,可以使用云函数。
  2. 需要兼容旧版本:当需要兼容旧版本时,可以使用云函数。
  3. 喜欢函数式编程:当喜欢函数式编程风格时,可以使用云函数。

何时使用云对象

  1. 复杂的业务逻辑:当业务逻辑复杂,需要更好的代码组织时,可以使用云对象。
  2. 需要更好的类型支持:当需要更好的类型支持时,可以使用云对象。
  3. 需要更好的错误处理:当需要更好的错误处理时,可以使用云对象。
  4. 需要更好的用户体验:当需要更好的用户体验时,可以使用云对象。
  5. 喜欢面向对象编程:当喜欢面向对象编程风格时,可以使用云对象。

12. 总结

云函数和云对象是 uniCloud 提供的两种不同的服务端开发模式,它们各有优缺点,适用于不同的场景。

云函数的优点

  1. 简单直接:函数式编程风格,简单直接。
  2. 兼容性好:兼容性好,可以兼容旧版本。
  3. 学习成本低:学习成本低,容易上手。

云函数的缺点

  1. 代码组织差:代码组织差,不易维护。
  2. 类型支持差:类型支持差,无法提供类型提示。
  3. 错误处理差:错误处理差,需要手动处理。
  4. 交互界面差:交互界面差,需要手动处理。

云对象的优点

  1. 代码组织好:面向对象的方式,代码组织好,易于维护。
  2. 类型支持好:支持 JSDoc 注释,提供更好的类型提示和检查。
  3. 错误处理好:统一的错误处理机制,减少重复代码。
  4. 交互界面好:默认提供加载提示和错误处理,提升用户体验。
  5. 开发效率高:开发效率高,减少样板代码。

云对象的缺点

  1. 学习成本高:学习成本高,需要了解面向对象编程。
  2. 兼容性差:兼容性差,不支持旧版本。
  3. 性能可能差:性能可能差,可能会有更多的内存占用。

从云对象发布后,不再推荐使用传统云函数了。如果是以数据库操作为主,则推荐使用 clientDB,开发效率是最高的。如果服务器端不操作数据库外,或者还有复杂的、不宜公开在前端的逻辑,此时推荐使用云对象。