非常多人都在讨论全栈。全栈便是运用一种语言js吗?不止。语言的统一,下一步是协作的改善。这才可让语言统一发挥更大的价值。
--题记
背景
从2000年起始,xml做为数据交换格式起始流行,服务器拼接xml接口,客户端js获取xml内容,动态修改页面。
几年后,数据量更小的json替代了xml。
移动互联网到来后,由于客户端分裂,加剧了接口的泛滥。
一转眼,接口已然玩了20年了。其他技术飞速发展,而前后端交互却始终是接口,无什么创新。
js已然有了import、export,为何调用后端接口,不可像调用一个前端模块同样呢?
serverless,让这一切起始了变化。
亚马逊lambda提出了云函数的概念,再也不使用restful的url,但仍然是基于json交换前后端数据。
uniCloud最初亦以支持云函数为起始,但咱们发掘这仍不足优雅、简洁、直观、统一。
从HBuilderX 3.4 起始,uniCloud推出了“云对象”,让调用云端服务,真正变影像调用前端模块同样简单。
什么是云对象
云对象:服务器编写API,客户端调用API,再也不研发传输json的接口。思路更清晰、代码更精简。
例如服务端编写一个云对象news,该对象导出若干办法:add()、getList()、getDetailById()、softDel()、changeContent()、allowPublic()、addComment()、getComments()...等。
客户端的js则能够 import 这个news云对象,而后直接调用add等办法。
服务器示例代码如下:
HBuilderX中在uniCloud/cloudfunctions目录新建云函数/云对象,选取类型为云对象,起名为news。打开云对象入口index.obj.js,导出一个add办法。 // 云对象名:news
module.exports = {
add(title, content) {
title = title.trim()
content = content.trim()
if(!title || !content) {
return{
errCode:INVALID_NEWS,
errMsg: 标题或内容不可为空
}
}
// ...其他规律
return {
errCode: 0,
errMsg: 创建成功
}
}
}而后在客户端的js中,import这个news对象,调用它的add办法。 const news = uniCloud.importObject(news) //第1步导入云对象
async function add () {
try {
const res = await news.add(title demo, content demo) //导入云对象后就能够直接调用该对象的办法了,重视运用异步await
uni.showToast({
title: 创建成功
})
} catch (e) { // 符合uniCloud响应体规范 https://uniapp.dcloud.net.cn/uniCloud/cf-functions?id=resformat,自动抛出此错误
}
}能够看到云对象的代码非常清晰,代码行数亦仅有27行。
而一样的规律,运用传统的接口方式则需要更加多代码,见下: // 传统方式调用云函数-云函数代码
// 云函数名:news
// 云函数入口index.js内容如下
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_NEWS,
errMsg: NEWS标题或内容不可为空
}
}
// ...省略其他规律
return {
errCode: 0,
errMsg: 创建成功}
}
}return {
errCode: METHOD_NOT_FOUND,
errMsg: `Method[${method}] not found`
}
};
// 传统方式调用云函数-客户端代码
async function add () {
try {
constres = uniCloud.callFunction({name: news,
data: {
method: add,
params: {
title: title demo,
content: content demo
}
}
})
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
})
}
}以上传统研发需要68行代码,对比云对象的27行代码,能够说“又丑又长”
更加多强大功能预处理与后处理
无论请求云对象的哪个办法,起始前都会经过_before办法,结束会执行_after办法。这有助于统一的提前校验和格式化错误。
示例: // news/index.obj.js
module.exports = {
_before: function(){
this.startTime = Date.now() // 在before内记录起始时间并在this上挂载,以供后续流程运用
const methodName = this.getMethodName() // 获取当前请求的云对象办法名
if(methodName === add && !this.getUniIdToken()) {
throw new Error(token不存在)
}
},
add: function(title = , content =) {
if(title === abc) {
throw new Error(abc不是一个合法的news标题)
}
return {
errCode: 0,
errMsg: 创建成功
}
},
_after(error, result) {
if(error) {
throw error // 倘若办法抛出错误,亦直接抛出不处理
}
result.timeCost = Date.now() - this.startTime
return result
}
}云对象的返回值兼容uniCloud响应体规范
云对象返回值默认为uniCloud响应体规范,方便客户端统一拦截错误。
无论网络反常,还是token过期,都能够统一拦截提示。
详见uniCloud响应体规范 自动表示交互界面
每次写客户端联网的代码时,研发者都免不了重复写一堆代码:先调用loading等待框,联网结束后再关闭loading,倘若服务器反常则弹出提示框。
原来的写法(22行): uni.showLoading({
title:联网中...
})
uni.request({
url: "xxxx",
success: (res) => {
uni.showToast({
title: 添加成功,
icon: success,
mask: true,
duration: duration
});
},
fail:(err) => {
uni.showModal({
content: err.errMsg,
showCancel: false
});
},
complete: () =>{
uni.hideLoading();
}
});此刻,调用云对象的办法时,默认自带以上功能。 在请求联网起始时表示loading等待框,结束后隐匿loading倘若请求报错,表示弹窗(亦可配置为表示Toast)const news = uniCloud.importObject(news) //第1步导入云对象
try {
await news.add(title demo, content demo) //导入云对象后就能够直接调用该对象的办法了,重视运用异步await
uni.showToast({
title: 添加成功
})
} catch (e) {}如上,原来需要23行的代码,此刻7行就能够搞定!
当然,这些UI策略都能够自定义。 URL化
为了历史兼容思虑,云对象同期供给了URL化方法。研发者仍然能够把一个云对象转换为一个http的url接口。
总结
运用云对象带来的许多好处: 更清晰的规律更精简的代码更少的协作成本(以及矛盾)客户端调用时在ide里有完善的代码提示,办法参数均可提示。(传输json可没法在ide里提示)自动支持uniCloud响应体规范,方便错误拦截和统一处理
仔细认识云对象,文档参见:
https://uniapp.dcloud.net.cn/uniCloud/cloud-obj.html
|