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

背景

从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

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理