cache-im介绍

背景

原来的Chatroom实例在聊天室组件中,而这次开发的答题器需要接收Chatroom消息。
当时列了几种解决办法:

  1. 把聊天室里面的Chatroom实例暴露出来
  2. Chatroom提供了getInstance方法,可以在答题器组件中取得单例。
  3. 答题器自己实例化一个Chatroom。
  4. 将Chatroom实例从聊天室组件抽出来,做一个分发器,各组件作为订阅者去监听分发器。

第一种办法的问题是:1.组件耦合 2.Chatroom实例化时接收onmsgs回调,不能通过订阅的方式来获取消息,然而两个组件拿到消息之后的处理逻辑又不一样
第二种办法的问题同第一种的第二条,并且需要保证聊天室组件中的Chatroom先实例化。
第三种办法的问题是:需要新的账号,并且发消息的地方也需要。

最终选择了第四种方案。

目标

对于发送方来说:
发消息的时候格式规范化。

对于接收方来说:
组件能够分类接收custom、text、image等云信类别的消息;
组件能够按云信返回消息的顺序接收被派发的消息;
组件可以省去消息判断逻辑,减少冗余消息的干扰:比如开始答题,若没有中间层分发,那么组件会拿到所有的消息自己过滤,去遍历每一个消息,看看type是否为custom且content.eventType是否为开始答题;
省略cache初始化过程;(尚未实现)

术语

(中文-->英文:解释)

云信消息类型-->YXTypes:可以通过msg.type取得,值可能是notification、custom、tip、text、image等。

唯一事件名称-->eventName:用于唯一标识一个事件,如answerSheet#custom_start_answer,即 业务+云信消息类别+具体事件名。

事件类型-->eventType:移动端、前端共用,用于标识主动发送的消息(像系统的notification消息属于被动消息)属于哪种类别,放在msg的content字段中。msgEvent默认根据此来判断是否匹配。

Chatroom:指云信聊天室。

简写

{root} : cache-im/src/im/

设计

消息流图

类图

流程图

使用

需要先在页面中引入云信Chatroom文件,可以在这里下载

发送方

// entry.js
IMCache.getInstance(options);

// component.js
var cache = IMCache.getInstance();
cache.sendCustomMsg({eventType:constant.ANSWER_SHEET_START_ANSWER},callback);   // constant.ANSWER_SHEET_START_ANSWER从{root}constant.js中取得

接收方

回调接收的参数可参考云信文档

// entry.js
IMCache.getInstance(options);

// component.js
var cache = IMCache.getInstance();

cache._$addEvent('msgs',function(msgs){...});

// 即msgs:YXTypes
cache._$addEvent('msgs:custom',function(msgs){...});
cache._$addEvent('msgs:text',function(msgs){...});  

cache._$addEvent('connect',function(chatroom){...});
cache._$addEvent('error',function(error){...});
cache._$addEvent('willConnect',function(obj){...});
cache._$addEvent('disConnect',function(error){...});
cache._$addEvent(xProcessor.CUSTOM.START_ANSWER,function(msgs){...});   // xProcessor在{root}processors/下
... // 具体可参考各processor

:接收到msg.content已经被JSON.parse过

扩展

一、新建processor

在{root}processors创建继承自processor的子类。以下的xxx代表业务范畴,如answerSheet代表答题器,它并不具体指某个组件。

processor主要做的事情就是:定义这个业务范畴需要派发的消息。有个误区需要避免:比如聊天室这个业务范畴,可能其中的聊天室组件需要监听答题器的点赞事件,但是点赞消息并不会归为聊天室的processor中。

/**
 * xxx处理器
 *
 * @version  1.0
 * @author   hzliuzongyuan <hzliuzongyuan@corp.netease.com>
 * @module   pool/cache-im/src/im/processors/xxxProcessor
 */
NEJ.define([
    'base/klass',
    './processor.js',
    'pool/edu-front-util/src/util',
    '../constant.js'
],function(
    k, 
    p,
    util,
    constant,
    exports,
    pro
){
    var xxxProcessor = k._$klass();
    pro = xxxProcessor._$extend(p.Processor);

    pro.__init = function (options) {
        this.prefix = 'xxx';    // 必填,生成eventName的时候需要用到
        this.__super(options,exports);  // 同上
    };

      // custom类消息,每个对象可以填name、eventType、eventName(默认自动生成)、match、handle等属性,具体可以参见{root}msgEvent.js
    pro.customList = function () {
        return [
            {
                name:'connectBrain',    // 用于生成eventName
                eventType:constant.XXX_CONNECT_BRAIN
            }
        ]
    };

      // 类似还有imageList、tipList等,即YXTypes+List,exports.XXX中的XXX即是据此生成的
    pro.textList = function () {
        return [
            {
                name: 'throwDogFood',
                  // 默认是判断this.eventType==msg.content.eventType,可以自己重写
                match: function (msg) {
                    if(msg.text.indexOf('狗粮')!==-1){
                        return true;
                    }
                }
            }
        ]
    };

    // 必须为.Processor,在cache.js中会用到
    exports.Processor = xxxProcessor;
});

二、在{root}list.js中添加processor

三、在{root}constant.js中添加eventType

Q&A

为什么不分发单个消息

单个消息虽然简化了处理逻辑,但可能浪费性能,比如每接收到一条文本则将消息插入到文档中。

为什么运行时才暴露唯一事件名?

如果直接在相应Processor的exports里面暴露,直观是直观了,但是写起来比较麻烦,因为除了上述提到的值之外,还要写key,比如exports.CUSTOM.START_ANSWER。而且手写还可能出错,并且可以不按照规范写,比如直接写成exports.START_ANSWER。
所以这是为了简化人工、规范化。

什么时候才能取得eventName?

processor实例化的时候便会生成eventName,cache会在实例化的时候实例化各processor,也就是说只要先实例化了cache就可以取得了。
一般的使用场景是:

var cache = IMCache.getInstance();
cache.addEvent(XXProcessor.CUSTOM.XXX,function(){});

为什么发送的是eventType,监听的是eventName

首先eventType未必是唯一的,虽然暂时是。现在我们用这个对custom消息进行区分,当以后我们要对notification或者其它云信消息类型也加以区分的时候,按理来说是允许eventType重复的,毕竟可以根据云信消息类型来区分,但是监听方法_$addEvent的第一个参数需要是唯一的。
还有个问题是,如果我们想根据消息本身的内容来新增一个事件时,比如根据text消息内容是否包含「狗粮」,匹配「扔狗粮」事件。如果我们以eventType的形式来接收,那么要给这类事件也分配一个eventType作为标识,而eventType是移动端、前端共用的,这样杂糅在一起不好。

为什么要分processor

我们最简单的分发器就是写一个这样的数组:

[{
    eventType:1,
    handle:function(msg){

    }
},{
    eventType:2,
    handle:function(msg){
        
    }
}...]

然后消息来了,遍历每条消息,看xx字段是否能匹配其中一个项,匹配则调用相应的handle方法,并且派发该消息。

这样我们需要集中管理这个数组,等慢慢积累之后很难维护,分processor其实就是解决这个问题的一种途径。

为什么一个消息只能匹配一个事件

暂时是这样,之后如果遇到相应的需求,也可以放开,不会对之前的逻辑有影响。

为什么不用NIM,而用Chatroom?

NIM包含了好友管理、群组等复杂功能,暂时用不上。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • 这篇笔记主要包含 Vue 2 不同于 Vue 1 或者特有的内容,还有我对于 Vue 1.0 印象不深的内容。关于...
    云之外阅读 5,044评论 0 29
  • 点击查看原文 Web SDK 开发手册 SDK 概述 网易云信 SDK 为 Web 应用提供一个完善的 IM 系统...
    layjoy阅读 13,652评论 0 15
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,392评论 25 707
  • 山式 树式 风吹树式 战士二式 站3 三角伸展式 幻椅 骆驼 束角式。 坐角 牛面式 鳄鱼扭转1
    随笔s阅读 296评论 0 0