cloud-obj.md 5.4 KB
Newer Older
雪洛's avatar
雪洛 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
## 云对象

> 新增于 HBuilderX 3.4.0

云对象本质上是对云函数的封装,和传统方式通过callFunction调用云函数相比,云对象写法更简单,调用更清晰。另外云对象默认支持[uniCloud响应体规范](uniCloud/cf-functions.md?id=resformat),对于满足规范的错误响应会在客户端自动抛出错误,开发者可以少写很多罗里吧嗦的判断。

以多action云函数为例,对比一下云对象和传统云函数

**传统callFunction方式代码如下:**

```js
// 传统方式调用云函数-云函数代码
// 云函数名:user-center
// 云函数入口index.js内容如下
'use strict';
exports.main = async (event, context) => {
	const {
		action,
		params
	} = event
	switch(action) {
		case 'updateUser': {
			const {
				nickname,
				age
			} = params
			// 简化演示逻辑,此处不演示token校验
			if(!nickname) {
				return {
					errCode: 'INVALID_NICKNAME',
					errMsg: '昵称不正确'
				}
			}
			return {
				errCode: 0,
				errMsg: '更新成功'
			}
		}
	}
	return {
		errCode: 'ACTION_NOT_FOUND',
		errMsg: `action[action] not found`
	}
};

// 传统方式调用云函数-客户端代码
async function updateUser () {
	try {
		const res = uniCloud.callFunction({
			name: 'user-center', 
			data: {
				action: 'updateUser',
				params: {
					nickname: 'dc',
					age: 10
				}
			}
		})
		const {
			errCode,
			errMsg
		} = res.result
		if(errCode) {
			uni.showModal({
				title: '更新失败',
				content: errMsg,
				showCancel: false
			})
			return
		}
		uni.showToast({
			title: '更新成功'
		})
	} catch (e) {
		uni.showModal({
			title: '更新失败',
			content: e.message,
			showCancel: false
		})
	}
}
```

**使用云对象的写法如下:**

```js
// 使用云对象的写法-云对象代码
// 云对象名:user-center
// 云对象入口index.obj.js内容如下
module.exports = {
	updateUser(nickname, age) {
		if (!nickname) {
			return {
				errCode: 'INVALID_NICKNAME',
				errMsg: '昵称不正确'
			}
		}
		return {
			errCode: 0,
			errMsg: '更新成功'
		}
	}
}

// 使用云对象的写法-客户端代码
const userCenter = uniCloud.importObject('user-center')
async function updateUser () {
	try {
		const res = await userCenter.updateUser('dc', 10)
		uni.showToast({
			title: '更新成功'
		})
	} catch (e) {
		// 此形式响应符合uniCloud响应体规范中的错误响应,自动抛出此错误
		// {
		// 	errCode: 'INVALID_NICKNAME',
		// 	errMsg: '昵称不正确'
		// }
		uni.showModal({
			title: '更新失败',
			content: e.errMsg,
			showCancel: false
		})
	}
}
```

可以看到大量的业务无关代码被简化掉,开发效率UP。此外通过`ObjectName.ActionName`的方式调用云函数和云端写法完全一致,心智负担大幅减小。请阅读以下内容深入了解云对象

## 规范

云对象和云函数都在cloudfunctions目录下,但是不同于云函数,云对象的入口为`index.obj.js`,而云函数则是`index.js`**为正确区分两者uniCloud做出了限制,云函数内不可存在index.obj.js,云对象内也不可存在index.js。**一个标准的云对象入口应导出一个对象,如下:

对象内每个键值对是一个action

```js
// user-center/index.obj.js
module.exports = {
	updateUser: async function(nickname, age) { 
		console.log(nickname, age)
	} // action updateUser
}
```

云对象也可以引用公共模块或者npm上的包,引用方式和云函数完全一致。

### 客户端调用@call-by-client

客户端通过`uniCloud.importObject`方法获取云对象的实例。用法如下

```js
const userCenter = uniCloud.importObject('user-center')
const res = await userCenter.updateUser('dc', 10) // 传入参数 nickname 和 age,参数和云对象内的action完全一致
```

### 客户端调用返回值@return-value

客户端拿到云对象的响应结果后,会自动进行结果的处理。

- 如果是正常的结果(errCode为假值[0, false, null, undefined, ...]或者结果内不含errCode)则将结果直接返回
- 如果是报错的结果(errCode为真值)将结果内的errCode和errMsg组合为错误对象抛出
- 如果是其他云函数未捕获的错误,直接将错误码和错误信息组合成错误对象抛出

前端抛出的错误对象上有以下属性

|属性名		|类型				|是否必备	|说明													|
|--			|--					|--			|--														|
|errCode	|string|number	|否			|错误码													|
|errMsg		|string				|否			|错误信息												|
|requestId	|string				|否			|当前请求的requestId									|
|detail		|Object				|否			|完成的错误响应(仅在响应符合uniCloud响应体规范时才有)	|

详见以下示例:

```js
// user-center/index.obj.js
module.exports = {
	updateUser: async function(nickname, age) { 
		if(!nickname) {
			return {
				errCode: 'INVALID_NICKNAME',
				errMsg: '更新失败'
			}
		}
		return {
			errCode: 0,
			errMsg: '更新成功'
		}
	}
}

// 客户端代码
const userCenter = uniCloud.importObject('user-center')
try {
	// 不传username,云函数返回错误的响应
	await userCenter.updateUser()
} catch (e) {
	// e.errCode === 'INVALID_NICKNAME'
	// e.errMsg === '更新失败'
	// e.detail === {errCode: 'INVALID_NICKNAME',errMsg: '更新失败'}
	// e.requestId === 'xxxx'
}

try {
	const res = await userCenter.updateUser('dc', 10)
	// res = {errCode: 0,errMsg: '更新成功'}
} catch (e) {}
```