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