cloud-obj.md 6.7 KB
Newer Older
雪洛's avatar
雪洛 已提交
1 2 3 4
## 云对象

> 新增于 HBuilderX 3.4.0

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

雪洛's avatar
雪洛 已提交
7
以下面的云函数为例,对比一下云对象和传统云函数
雪洛's avatar
雪洛 已提交
8 9 10 11 12 13 14 15 16 17

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

```js
// 传统方式调用云函数-云函数代码
// 云函数名:user-center
// 云函数入口index.js内容如下
'use strict';
exports.main = async (event, context) => {
	const {
雪洛's avatar
雪洛 已提交
18
		method,
雪洛's avatar
雪洛 已提交
19 20
		params
	} = event
雪洛's avatar
雪洛 已提交
21 22
	switch(method) {
		case 'login': {
雪洛's avatar
雪洛 已提交
23
			const {
雪洛's avatar
雪洛 已提交
24 25
				username,
				password
雪洛's avatar
雪洛 已提交
26 27
			} = params
			// 简化演示逻辑,此处不演示token校验
雪洛's avatar
雪洛 已提交
28
			if(!username) {
雪洛's avatar
雪洛 已提交
29
				return {
雪洛's avatar
雪洛 已提交
30 31
					errCode: 'INVALID_USERNAME',
					errMsg: '用户名不正确'
雪洛's avatar
雪洛 已提交
32 33
				}
			}
雪洛's avatar
雪洛 已提交
34
			// ...省略其他逻辑
雪洛's avatar
雪洛 已提交
35 36
			return {
				errCode: 0,
雪洛's avatar
雪洛 已提交
37
				errMsg: '登录成功'
雪洛's avatar
雪洛 已提交
38 39 40 41
			}
		}
	}
	return {
雪洛's avatar
雪洛 已提交
42 43
		errCode: 'METHOD_NOT_FOUND',
		errMsg: `Method[${method}] not found`
雪洛's avatar
雪洛 已提交
44 45 46 47
	}
};

// 传统方式调用云函数-客户端代码
雪洛's avatar
雪洛 已提交
48
async function login () {
雪洛's avatar
雪洛 已提交
49 50 51 52
	try {
		const res = uniCloud.callFunction({
			name: 'user-center', 
			data: {
雪洛's avatar
雪洛 已提交
53
				method: 'login',
雪洛's avatar
雪洛 已提交
54
				params: {
雪洛's avatar
雪洛 已提交
55 56
					username: 'dc',
					password: '123456'
雪洛's avatar
雪洛 已提交
57 58 59 60 61 62 63 64 65
				}
			}
		})
		const {
			errCode,
			errMsg
		} = res.result
		if(errCode) {
			uni.showModal({
雪洛's avatar
雪洛 已提交
66
				title: '登录失败',
雪洛's avatar
雪洛 已提交
67 68 69 70 71 72
				content: errMsg,
				showCancel: false
			})
			return
		}
		uni.showToast({
雪洛's avatar
雪洛 已提交
73
			title: '登录成功'
雪洛's avatar
雪洛 已提交
74 75 76
		})
	} catch (e) {
		uni.showModal({
雪洛's avatar
雪洛 已提交
77
			title: '登录失败',
雪洛's avatar
雪洛 已提交
78 79 80 81 82 83 84 85 86 87 88 89 90 91
			content: e.message,
			showCancel: false
		})
	}
}
```

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

```js
// 使用云对象的写法-云对象代码
// 云对象名:user-center
// 云对象入口index.obj.js内容如下
module.exports = {
雪洛's avatar
雪洛 已提交
92 93
	login(username, password) {
		if (!username) {
雪洛's avatar
雪洛 已提交
94
			return {
雪洛's avatar
雪洛 已提交
95 96
				errCode: 'INVALID_USERNAME',
				errMsg: '用户名不正确'
雪洛's avatar
雪洛 已提交
97 98
			}
		}
雪洛's avatar
雪洛 已提交
99
		// ...登录逻辑
雪洛's avatar
雪洛 已提交
100 101
		return {
			errCode: 0,
雪洛's avatar
雪洛 已提交
102
			errMsg: '登录成功'
雪洛's avatar
雪洛 已提交
103 104 105 106 107 108
		}
	}
}

// 使用云对象的写法-客户端代码
const userCenter = uniCloud.importObject('user-center')
雪洛's avatar
雪洛 已提交
109
async function login () {
雪洛's avatar
雪洛 已提交
110
	try {
雪洛's avatar
雪洛 已提交
111
		const res = await userCenter.login('dc', '123456')
雪洛's avatar
雪洛 已提交
112
		uni.showToast({
雪洛's avatar
雪洛 已提交
113
			title: '登录成功'
雪洛's avatar
雪洛 已提交
114 115 116 117
		})
	} catch (e) {
		// 此形式响应符合uniCloud响应体规范中的错误响应,自动抛出此错误
		// {
雪洛's avatar
雪洛 已提交
118 119
		// 	errCode: 'INVALID_USERNAME',
		// 	errMsg: '用户名不正确'
雪洛's avatar
雪洛 已提交
120 121
		// }
		uni.showModal({
雪洛's avatar
雪洛 已提交
122
			title: '登录失败',
雪洛's avatar
雪洛 已提交
123 124 125 126 127 128 129
			content: e.errMsg,
			showCancel: false
		})
	}
}
```

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

## 规范

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

雪洛's avatar
雪洛 已提交
136
对象内每个键值对是一个处理方法
雪洛's avatar
雪洛 已提交
137 138 139 140

```js
// user-center/index.obj.js
module.exports = {
雪洛's avatar
雪洛 已提交
141 142 143
	login: async function(username, password) { 
		console.log(username, password)
	} // login方法
雪洛's avatar
雪洛 已提交
144 145 146 147 148 149 150 151 152 153 154
}
```

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

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

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

```js
const userCenter = uniCloud.importObject('user-center')
雪洛's avatar
雪洛 已提交
155
const res = await userCenter.login('dc', '123456') // 传入参数 username 和 password,参数和云对象内的方法完全一致
雪洛's avatar
雪洛 已提交
156 157
```

雪洛's avatar
雪洛 已提交
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
### 云函数或云对象内调用@call-by-cloud

云函数或云对象内也可以调用同一服务空间内的云对象,用法和客户端调用云对象一致

```js
const userCenter = uniCloud.importObject('user-center')
const res = await userCenter.login('dc', '123456') // 传入参数 username 和 password,参数和云对象内的方法完全一致
```

### 跨服务空间调用云对象@call-by-cloud-cross-space

云端或者客户端均有uniCloud.init方法可以获取其他服务空间的uniCloud实例,使用此实例的importObject可以调用其他服务空间的云对象,参考:[](uniCloud/concepts/space.md?id=multi-space)

客户端无论腾讯阿里均支持。云端`uniCloud.init`方法仅腾讯云支持,且仅能获取同账号下的腾讯云服务空间的uniCloud实例。

**示例代码**

```js
const mycloud = uniCloud.init({
	provider: 'tencent',
	spaceId: 'xxx'
})
const userCenter = mycloud.importObject('user-center')
const loginRes = await mycloud.login('dc', '123456')
```

### 云对象的返回值@return-value
雪洛's avatar
雪洛 已提交
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205

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

- 如果是正常的结果(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 = {
雪洛's avatar
雪洛 已提交
206 207
	login: async function(username, password) { 
		if(!username) {
雪洛's avatar
雪洛 已提交
208
			return {
雪洛's avatar
雪洛 已提交
209 210
				errCode: 'INVALID_USERNAME',
				errMsg: '登录失败'
雪洛's avatar
雪洛 已提交
211 212 213 214
			}
		}
		return {
			errCode: 0,
雪洛's avatar
雪洛 已提交
215
			errMsg: '登录成功'
雪洛's avatar
雪洛 已提交
216 217 218 219 220 221 222 223
		}
	}
}

// 客户端代码
const userCenter = uniCloud.importObject('user-center')
try {
	// 不传username,云函数返回错误的响应
雪洛's avatar
雪洛 已提交
224
	await userCenter.login()
雪洛's avatar
雪洛 已提交
225
} catch (e) {
雪洛's avatar
雪洛 已提交
226 227 228
	// e.errCode === 'INVALID_USERNAME'
	// e.errMsg === '登录失败'
	// e.detail === {errCode: 'INVALID_USERNAME',errMsg: '登录失败'}
雪洛's avatar
雪洛 已提交
229 230 231 232
	// e.requestId === 'xxxx'
}

try {
雪洛's avatar
雪洛 已提交
233
	const res = await userCenter.login('dc', '123456')
雪洛's avatar
雪洛 已提交
234 235 236 237
	// res = {errCode: 0,errMsg: '更新成功'}
} catch (e) {}
```

雪洛's avatar
雪洛 已提交
238 239 240
## 本地运行@run-local

云对象无法直接本地运行,可以通过其他云函数调用本地云对象(在调用云对象的云函数右键本地运行),或者客户端调用本地云对象的方式来实现云对象的本地运行。