资讯专栏INFORMATION COLUMN

YodaOS 中是如何生成 API 的

Tikitoo / 2016人阅读

摘要:系统在初始化时,会加载所有,然后分别在和生成对应的。那么在中,又是如何将上述的生成为开发者直接使用的接口的呢下面就为大家介绍我们引入的。它接受一个对象,然后会遍历原型链中的对象,并且分别按照和去生成一个叫的对象,最后将这个对象返回给开发者。

在 Node.js 社区中,其实不乏通过 Markdown 生成 RESTful API 的框架,按照一定的格式约定好 API 所需要的数据,然后再通过解析 Markdown 文档,将这些关键数据提取出来,最后生成数据库模型和 HTTPS 服务。

YodaOS 作为一个前端操作系统,同样使用了类似的技术。YodaOS 中的应用分为:lightapp 和 extapp,前者是集成在语音交互运行时(Vui-daemon)进程内部的轻应用,它主要是用于一个交互简单,需要快速响应的场景,比如音量控制、系统控制等。后者作为一个独立的进程,通过 Child Process 与主进程通讯,使用场景主要是音乐、游戏、电话等需要长时期使用的应用。

为什么要有轻应用?轻应用更像是一个脚本,每当用户一次进行一次交互,只需要从预先加载的脚本中调用定义在对应脚本的函数即可完成一次响应,往往这类应用交互比较简单,如果为此要创建在每次交互的过程中进行一次
ipc 甚至 fork 时,无论对性能还是内存来说,都是比较浪费的。

在设计之初,我们期望对于开发者来说,并不需要针对不同类型的应用,只需要在 package.json 中修改类型即可,YodaOS API 应当保持完全一致。这样的话,我们则面对一个问题,即使是能做到高度抽象,也需要在每次新增一个接口时,修改两处代码,这其实是有违我们的设计初衷的。

**

API Descriptor

**

为此,我们引入了 API Descriptor 的概念:https://github.com/yodaos-pro...。可以把它看作是用 JavaScript 写的 DSL,它用于描述每个 YodaOS API,包括命名空间、事件、方法等定义。系统在初始化时,会加载所有 API Descriptor,然后分别在 lightapp 和 extapp 生成对应的 API。

Object.assign(ActivityDescriptor.prototype,
{

/**
 * When the app is active.
 * @event yodaRT.activity.Activity#active
 */
active: {
  type: "event"
},
/**
 * When the Activity API is ready.
 * @event yodaRT.activity.Activity#ready
 */
ready: {
  type: "event"
},
/**
 * When an activity is created.
 * @event yodaRT.activity.Activity#create
 */
created: {
  type: "event"
}

}
)
上面的代码分别定义了 Activity 中的几个事件:active、ready 和 create。因此,在任何应用中都可以这样写:

module.exports = activity => {
activity.on("active", () => console.log("app activated"))
activity.on("ready", () => console.log("app is ready"))
activity.on("created", () => console.log("app is created"))
}
接下来我们再看看“方法”是如何定义:

Object.assign(ActivityDescriptor.prototype,
{

/**
 * Get all properties, it contains the following fields:
 * - `deviceId` the device id.
 * - `deviceTypeId` the device type id.
 * - `key` the cloud key.
 * - `secret` the cloud secret.
 * - `masterId` the userId or masterId.
 *
 * @memberof yodaRT.activity.Activity
 * @instance
 * @function get
 * @returns {Promise}
 * @example
 * module.exports = function (activity) {
 *   activity.on("ready", () => {
 *     activity.get().then((props) => console.log(props))
 *   })
 * }
 */
get: {
  type: "method",
  returns: "promise",
  fn: function get () {
    return Promise.resolve(this._runtime.getCopyOfCredential())
  }
},

}
)
可以看到,与定义事件的方式一样,只需要在 Descriptor 的原型链中,增加对应的对象,然后设置类型(type)为 method 即可,然后在 fn 中实现函数。

module.exports = activity => {
activity.get().then(

(data) => console.log("credentialse is", data),
(err) => console.error("something went wrong", err))

}
这样除了 API 定义可以统一起来了,也能比较方便地基于 JSDoc 生成统一的 API Reference 给开发者,使得整个 API 的修改能做到简单易读、门槛低和修改成本低等。

**

API Translator

**

那么在 YodaOS 中,又是如何将上述的 Descriptor 生成为开发者直接使用的接口的呢?下面就为大家介绍我们引入的 Translator。

Translator 是按照我们支持的应用类型对应的,因此对于 lightapp 和 extapp 来说,我们也分为两个 translator:

进程内的 https://github.com/yodaos-pro...
进程间的 https://github.com/yodaos-pro...

本文并不具体展开每个 translator 的工作原理,但会做一些简单的流程介绍。以 translator-ipc 为例:

module.exports.translate = translate
function translate (descriptor) {
if (typeof process.send !== "function") {

throw new Error("IpcTranslator must work in child process.")

}
var activity = PropertyDescriptions.namespace(null, descriptor, null, null)
listenIpc()
return activity
}

每个 translator 提供一个函数,即 translate(descriptor)。它接受一个 descriptor 对象,然后会遍历原型链中的对象,并且分别按照 namespace、event 和 method 去生成一个叫 activity 的对象,最后将这个对象返回给开发者。

当开发者在使用某个 API 时,activity 对象会按照 translator 预先生成(约定)好的逻辑调用到服务端(Vui-daemon),最后再通过 Promise 返回调用后的结果,从而完成一次接口调用。

**

后记

**

本文简单介绍了 YodaOS 在 API 设计过程中,如何利用 DSL,解决 YodaOS API 在多种应用形态保持一致性。以此,我们希望抛砖引玉:

帮助读者更好地了解 YodaOS API 的生成过程
帮助读者了解到 DSL,也能将这种思路应用在自己的项目中
如有更多问题,欢迎评论,或者直接在 GitHub 上给我们提问题:Build software better, together

**

参考

**

D-Bus introspection:Introspection - Using of D-Bus
YodaOS:YODAOS Project

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/102911.html

相关文章

  • 了解语音交互:从“若琪,今天杭州天气”发生了什么?

    摘要:接下来,由会通过上传音频数据,云端通过一系列算法最终将语音数据转换为两部分结果纯文本,表示这段音频数据中用户所说的话,比如若琪今天的天气。 本文是面向 Web 开发者所写,介绍关于语音交互的一篇科普性质的文章,希望借助这篇文章,让开发者了解到什么是语音交互,以及在 YodaOS 中的技术实现。不了解YodaOS是什么?点击这里回顾。 作为 Web 开发者,相信在面试时常会被问到浏览器输...

    kel 评论0 收藏0
  • YodaOS:一个属于 Node.js 社区操作系统

    摘要:的架构跟类似,从下至上,由系统服务和应用框架组成。依托于提供的运行时,从到现在的和,在构建工具领域,社区也不断涌现出非常卓越的开源项目来。 大家好,很开心在这里宣布 YodaOS 开源了。他将承载 Rokid 4年以来对于人工智能和语音交互领域的沉淀,并选择 Node.js 作为操作系统的一等开发公民,全部开放给社区。 showImg(https://segmentfault.com/...

    Batkid 评论0 收藏0
  • 第八期杭州NodeParty x Rokid技术分享会回顾

    摘要:月号,杭州和联合主办的第八期技术分享会,在公司如期举行。张伟林,宋小菜资深前端开发工程师,年,霹雳迷,已手残的纸牌魔术师,喜欢神奇的东西,技术栈从上向下不断横向纵向贯穿,目前在寻找前后端大一统思想的路上越走越偏。 showImg(https://segmentfault.com/img/bVbkWN4?w=3000&h=1686); 12 月 9 号,杭州 NodeParty 和 Ro...

    gself 评论0 收藏0
  • YodaOS开发套件征集活动

    摘要:为了能让感兴趣的开发者小伙伴第一时间体验到,联合社区赶在春节前发起开发套件试用征集活动,该套件是基于自研语音解决方案平台打造而成。与此同时,我们也同样提供高度定制化模块化的整体架构,开发者亦可方便地选择想要集成的模块对整个操作系统重新组装。 1月28日,Rokid为人机交互设备开发的开源人工智能操作系统——YodaOS正式上线,可用于智能音箱、智能家居、智能穿戴和车载等多种设备和场景。...

    canger 评论0 收藏0
  • YodaOS开发套件征集活动

    摘要:为了能让感兴趣的开发者小伙伴第一时间体验到,联合社区赶在春节前发起开发套件试用征集活动,该套件是基于自研语音解决方案平台打造而成。与此同时,我们也同样提供高度定制化模块化的整体架构,开发者亦可方便地选择想要集成的模块对整个操作系统重新组装。 1月28日,Rokid为人机交互设备开发的开源人工智能操作系统——YodaOS正式上线,可用于智能音箱、智能家居、智能穿戴和车载等多种设备和场景。...

    call_me_R 评论0 收藏0

发表评论

0条评论

Tikitoo

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<