关于uni-app:云对象-重新定义前后端交互

7次阅读

共计 3597 个字符,预计需要花费 9 分钟才能阅读完成。

背景

从 2000 年开始,xml作为数据交换格局开始风行,服务器拼接 xml 接口,客户端 js 获取 xml 内容,动静批改页面。

几年后,数据量更小的 json 代替了xml

挪动互联网到来后,因为客户端决裂,加剧了接口的泛滥。

一转眼,接口曾经玩了 20 年了。其余技术飞速发展,而前后端交互却始终是接口,没有什么翻新。

js 曾经有了importexport,为什么调用后端接口,不能像调用一个前端模块一样呢?

serverless,让这所有开始了变动。

亚马逊 lambda 提出了云函数的概念,不再应用 restfulurl,但依然是基于 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') // 第一步导入云对象
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 {
        const res = 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 行代码,能够说“又丑又长”

更多弱小性能

1. 预处理与后处理

无论申请云对象的哪个办法,开始前都会通过 _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
    }
}

2. 云对象的返回值兼容 uniCloud 响应体标准

云对象返回值默认为uniCloud 响应体标准,不便客户端对立拦挡谬误。

无论网络异样,还是 token 过期,都能够对立拦挡提醒。

详见 uniCloud 响应体标准

3. 主动显示交互界面

每次写客户端联网的代码时,开发者都免不了反复写一堆代码:先调用 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') // 第一步导入云对象
try {await news.add('title demo', 'content demo') // 导入云对象后就能够间接调用该对象的办法了,留神应用异步 await
    uni.showToast({title: '增加胜利'})
} catch (e) {}

如上,原来须要 23 行的代码,当初 7 行就能够搞定!

当然,这些 UI 策略都能够自定义。

  1. URL 化

为了历史兼容思考,云对象同时提供了 URL 化计划。开发者依然能够把一个云对象转换为一个 httpurl接口。

总结

应用云对象带来的诸多益处:

  1. 更清晰的逻辑
  2. 更精简的代码
  3. 更少的合作老本(以及矛盾~)
  4. 客户端调用时在 ide 里有欠缺的代码提醒,办法参数均可提醒。(传输 json 可没法在 ide 里提醒)
  5. 主动反对 uniCloud 响应体标准,不便谬误拦挡和对立解决

更多云对象介绍,参见:https://uniapp.dcloud.net.cn/uniCloud/cloud-obj.html

正文完
 0