# 操作场景

当开发者已经拥有小程序账号,并已开通了云开发服务创建了云开发环境后,接下来就是开发小程序的客户端及服务端。

  • 客户端:在小程序端中直接操作云数据库和云存储,以及调用云函数。
  • 服务端:在云函数中操作云资源。

# 准备工作

# 基础库版本

您可以开发者工具的【详情】 中选择任意基础库版本,用于开发和调试旧版本兼容问题。

云开发能力从微信开发者工具基础库 2.2.3 开始支持。目前 2.2.3 或以上的基础库没有覆盖所有用户(覆盖率约 97% ),如需使上传的代码能够覆盖全量用户,请在 app.json / game.json 中增加字段"cloud":true。指定后,云能力可以在所有基础库中使用,并且如果云能力有更新,并不会随着基础库升级而自动升级,需在后续版本发布后重新上传。如 2.2.4 发布后,需重新上传才能将云能力更新至 2.2.4 版本的云能力。

# 安装依赖

云函数属于服务端,在云函数中运行的代码拥有不受限的数据库读写权限和云文件读写权限。云函数的运行环境是 Node.js,您可以利用第三方依赖,来帮助您更快地开发。

云开发提供了云端安装依赖,免去了在终端手动安装依赖的工作。但如果在您的环境中无法直接使用 npm install,比如需要走代理、使用自建的 npm 源站、本地调试云函数、使用其他包管理器如 yarn 等的情况,则不能使用工具的自动安装依赖,需手工执行相应依赖安装命令。您需要做以下工作:

  1. 安装 Node.js (opens new window) (包含 npm)。
  2. 在相关云函数的目录中安装 wx-server-sdk (opens new window) 依赖或 tcb-admin-node (opens new window) 依赖:
npm install --save wx-server-sdk
npm install --save tcb-admin-node

TIP

  • wx-server-sdk 是基于 tcb-admin-node开发的服务端 SDK,与小程序端的接口使用方式一致,能获得更一体的开发体验。但如果想获得更高级的功能,可使用 tcb-admin-node
  • 需要特别注意的是,在 wx-server-sdk 依赖中不再兼容 successfailcomplete 回调,总是只会返回 Promise

具体操作可参考 使用 npm (opens new window)

# QuickStart 项目

在微信开发者工具中新建项目,勾选创建 “云开发 QuickStart 项目”,单击创建即可得到一个展示云开发基础能力的示例小程序。该小程序由三个部分组成:

  1. miniprogram:小程序的结构,包括主体部分(App)和各个页面,详情见 小程序目录结构 (opens new window)
  2. project.config.json:项目配置文件,可以用于对项目进行配置。 QuickStart 项目的配置文件中新增了 cloudfunctionRoot 字段:指定本地已存在的目录作为云函数的本地根目录,如指定cloudfunctions为云函数的本地根目录:
{
  "cloudfunctionRoot": "cloudfunctions/"
}

其他配置项说明见 项目配置文件 (opens new window)

  1. cloudfunctions|(环境名):云函数根目录。在project.config.json中完成指定之后,云函数的根目录的图标会变成 “云目录图标”,右击根目录,可新建 Node.js 云函数,即云函数根目录下的第一级目录为云函数目录。在小程序中调用云函数前,需要先将该云函数部署到云端。如果对应云端存在该云函数,则会用特殊的云图标及 Nodejs 图标标明: 右击云函数目录,可将云函数上传并部署到云端。您可以选择两种方式:
    • 云端安装依赖:不使用 npm,直接在云端安装依赖。
    • 本地安装依赖:使用 npm,需要先在终端中手动安装依赖。

# 操作步骤

# 客户端使用云开发能力

客户端,这里指在小程序端中。客户端代码,均是用户使用 IDE 工具完成的前端代码。

如果您需要使用云开发能力,请确保:

  • 在 app.json / game.json 中, 增加了字段 "cloud": true
  • 在 project.config.json 中,增加了字段 cloudfunctionRoot 用于指定存放云函数的目录。

# 初始化云开发能力

此段代码需要加入在 IDE 中的 app.js 中,如下图所示:

//app.js
App({
  onLaunch: function () {

    if (!wx.cloud) {
      console.error('请使用 2.2.3 或以上的基础库以使用云能力')
    } else {
      wx.cloud.init({
        traceUser: true,
        env: 'test-uvk7u' //您当前的环境ID
      })
    }

    this.globalData = {}
  }
})

详情请参考 初始化能力文档 (opens new window)

?在用户管理中会显示使用云能力的小程序的访问用户列表,默认以访问时间倒叙排列,访问时间的触发点是在小程序端调用 wx.cloud.init 方法,且其中的 traceUser 参数传值为 true。

# 小程序操作存储资源

初始化完成后,客户端代码即可通过 SDK 对云开发的后台资源进行访问与操作。下述的是一个典型的存储资源的操作示例代码,您可以在您的前端代码中进行更多的存储类操作。

// 选择图片
wx.chooseImage({
    success: dRes => {
        // 上传图片
        const uploadTask = wx.cloud.uploadFile({
            cloudPath: `${Date.now()}-${Math.floor(Math.random(0, 1) * 10000000)}.png`, // 随机图片名
            filePath: dRes.tempFilePaths[0], // 本地的图片路径
            success: console.log,
            fail: console.error
        });
    },
    fail: console.error,
});

更多详情请参考 存储文档 (opens new window)

# 小程序操作数据库

初始化完成后,客户端代码即可通过 SDK 对云开发的提供的数据库进行资源操作。下述的是一个典型的数据库操作示例代码,您可以在您的前端代码中进行更多的数据库操作。

const db = wx.cloud.database();

db.collection('blog').get().then((res) => {
    let data = res.data;
    console.log(data);
});

更多详情请参考 数据库文档 (opens new window)

# 小程序调用云函数

当您的小程序需要计算能力/后台处理能力时,则需要在前端代码中调用云开发提供的函数能力。下述代码为典型的在客户端调用云函数的示例代码。

wx.cloud.callFunction({
    name: 'addblog', // 云函数名称
    data: { // 传到云函数处理的参数
        title: '云开发 CloudBase',
        content: '存储、数据库存、云函数'
    }
}).then(res => {
    console.log(res)
}).catch((err) => {
    console.error(err);
});

更多详情请参考 云函数文档 (opens new window)

# 服务端使用云开发能力

在很多应用场景中,后台也需要对存储、数据库等资源进行操作。如果您想在云函数中,操作文件、数据库和云函数资源,您可以使用我们提供的服务端 SDK 来进行开发。服务端下述的所有代码,均需要部署在云函数中。这里的示例均为使用云开发的服务端 SDK,即 tcb-admin-node,您也可以使用 wx-server-sdk

# 在云函数中初始化

// 初始化示例
const app = require('tcb-admin-node');

// 初始化资源
// 云函数下不需要secretId和secretKey。
// env如果不指定将使用默认环境
app.init({
  secretId: 'xxxxx',
  secretKey: 'xxxx',
  env: 'xxx'
});

//云函数下使用默认环境
app.init()

//云函数下指定环境
app.init({
  env: 'xxx'
});

详情请参考 初始化文档 (opens new window)

# 服务端操作文件资源

const app = require('tcb-admin-node');
app.init();

app.uploadFile({
    cloudPath: "cover.png",
    fileContent: fs.createReadStream(`${__dirname}/cover.png`)
}).then((res) => {
    console.log(res);
}).catch((err) => {
    console.error(err);
});;

详情请参考 存储文档 (opens new window)

# 服务端操作数据库

const app = require('tcb-admin-node');
app.init();
const db = app.database();

db.collection('blogs').limit(10).get().then((res) => {
    console.log(res);
}).catch((err) => {
    console.error(err);
});;

详情请参考 数据库文档 (opens new window)

# 服务端调用云函数

const app = require("tcb-admin-node");
app.init();

app.callFunction({
    name: 'addblog', // 云函数名称
    data: { // 传到云函数处理的参数
        title: '云开发 CloudBase',
        content: '存储、数据库存、云函数'
    }
}).then((res) => {
    console.log(res);
}).catch((err) => {
    console.error(err);
});

详情请参考 云函数文档 (opens new window)

# 语法糖

大部分的接口,目前都支持两种写法,分别是 Promise 和 Async/Await。Async/Await 本质上是基于 Promise 的一种语法糖,它只是把 Promise 转换成同步的写法而已。

# Promise

const app = require("tcb-admin-node");
app.init();

exports.main = async (event, context) => {
    return new Promise((resolve, reject) => {
    // 在 3 秒后返回结果给调用方(小程序 / 其他云函数)
    setTimeout(() => {
      resolve('hello world');
    }, 3000)
  });

# Async/Await

const app = require("tcb-admin-node");
app.init();

exports.main = async (event, context) => {
    let result = null;

    try {
        result = await app.callFunction({
            name: 'addblog', // 云函数名称
            data: { // 传到云函数处理的参数
                title: '云开发 CloudBase',
                content: '存储、数据库存、云函数'
            }
        });
    }
    catch (e) {
        return e;
    }

    return result;
};