uni-app 186多进程实现(一)

简介: uni-app 186多进程实现(一)

/app.js

class AppBootHook {
    constructor(app) {
        this.app = app;
    }
    configWillLoad() {
        // 此时 config 文件已经被读取并合并,但是还并未生效
        // 这是应用层修改配置的最后时机
        // 注意:此函数只支持同步调用
    }
    async didLoad() {
        // 所有的配置已经加载完毕
        // const app = this.app;
        // const ctx = await app.createAnonymousContext();
        // app.messenger.send
        // 可以用来加载应用自定义的文件,启动自定义的服务
        
    }
    async willReady() {
        // 所有的插件都已启动完毕,但是应用整体还未 ready
        // 可以做一些数据初始化等操作,这些操作成功才会启动应用
        // 例如:从数据库加载数据到内存缓存
    }
    async didReady() {
        // 应用已经启动完毕
        const app = this.app;
        const ctx = await app.createAnonymousContext();
        app.messenger.on('offline', user_id => {
            if (app.ws.user[user_id]) {
                app.ws.user[user_id].send(JSON.stringify({
                    msg: "fail",
                    data: '你的账号在其他设备登录'
                }));
                app.ws.user[user_id].close();
            }
        });
        app.messenger.on('send', e => {
            let { to_id, message, msg } = e;
            if (app.ws.user && app.ws.user[to_id]) {
                app.ws.user[to_id].send(JSON.stringify({
                    msg,
                    data: message
                }));
                app.ws.user[user.id].close();
            }
        });
    }
    async serverDidReady() {
        // http / https server 已启动,开始接受外部请求
        // 此时可以从 app.server 拿到 server 的实例
    }
}
module.exports = AppBootHook;

/app/controller/chat.js

// app/controller/chat.js
const Controller = require('egg').Controller;
class ChatController extends Controller {
    // 连接socket
    async connect() {
        const { ctx, app, service } = this;
        if (!ctx.websocket) {
            ctx.throw(400, '非法访问');
        }
        // console.log(`clients: ${app.ws.clients.size}`);
        // 监听接收消息和关闭socket
        ctx.websocket
            .on('message', msg => {
                // console.log('接收消息', msg);
            })
            .on('close', (code, reason) => {
                // 用户下线
                console.log('用户下线', code, reason);
                let user_id = ctx.websocket.user_id;
                // 移除redis中的用户上线记录
                service.cache.remove('online_' + user_id);
                if (app.ws.user && app.ws.user[user_id]) {
                    delete app.ws.user[user_id];
                }
            });
    }
    // 发送消息
    async send() {
        const { ctx, app, service } = this;
        // 拿到当前用户id
        let current_user_id = ctx.authUser.id;
        // 验证参数
        ctx.validate({
            to_id: {
                type: 'int',
                required: true,
                desc: '接收人/群id'
            },
            chat_type: {
                type: 'string',
                required: true,
                range: {
                    in: ['user', 'group']
                },
                desc: '接收类型'
            },
            type: {
                type: 'string',
                required: true,
                range: {
                    in: ['text', 'image', 'video', 'audio', 'emoticon', 'card']
                },
                desc: '消息类型'
            },
            data: {
                type: 'string',
                required: true,
                desc: '消息内容'
            },
            options: {
                type: 'string',
                required: true
            }
        });
        // 获取参数
        let { to_id, chat_type, type, data, options } = ctx.request.body;
        // 单聊
        if (chat_type === 'user') {
            // 验证好友是否存在,并且对方没有把你拉黑
            let Friend = await app.model.Friend.findOne({
                where: {
                    user_id: to_id,
                    friend_id: current_user_id,
                    isblack: 0
                },
                include: [{
                    model: app.model.User,
                    as: "userInfo"
                }, {
                    model: app.model.User,
                    as: "friendInfo"
                }]
            });
            if (!Friend) {
                return ctx.apiFail('对方不存在或者已经把你拉黑');
            }
            // 验证好友是否被禁用
            if (!Friend.userInfo.status) {
                return ctx.apiFail('对方已被禁用');
            }
            // 构建消息格式
            let from_name = Friend.friendInfo.nickname ? Friend.friendInfo.nickname : Friend.friendInfo.username;
            if (Friend.nickname) {
                from_name = Friend.nickname;
            }
            let message = {
                id: (new Date()).getTime(), // 唯一id,后端生成唯一id
                from_avatar: Friend.friendInfo.avatar,// 发送者头像
                from_name, // 发送者昵称
                from_id: current_user_id, // 发送者id
                to_id, // 接收人/群 id
                to_name: Friend.userInfo.nickname ? Friend.userInfo.nickname : Friend.userInfo.username, // 接收人/群 名称
                to_avatar: Friend.userInfo.avatar, // 接收人/群 头像
                chat_type: 'user', // 接收类型
                type,// 消息类型
                data, // 消息内容
                options: {}, // 其他参数
                create_time: (new Date()).getTime(), // 创建时间
                isremove: 0, // 是否撤回
            }
            // 视频,截取封面
            if (message.type === 'video') {
                message.options.poster = message.data + '?x-oss-process=video/snapshot,t_10,m_fast,w_300,f_png';
            }
            // 音频,带上音频时长
            if (message.type === 'audio') {
                options = JSON.parse(options);
                message.options.time = options.time || 1;
            }
            // 名片
            if (message.type === 'card') {
                // 验证名片用户是否存在
                message.options = JSON.parse(options)
            }
            ctx.sendAndSaveMessage(to_id, message);
            // 存储到自己的聊天记录中 chatlog_当前用户id_user_对方用户id
            service.cache.setList(`chatlog_${current_user_id}_${message.chat_type}_${to_id}`, message);
            // 返回成功
            return ctx.apiSuccess(message);
        }
        // 群聊
        // 验证群聊是否存在,且你是否在该群中
        let group = await app.model.Group.findOne({
            where: {
                status: 1,
                id: to_id
            },
            include: [{
                model: app.model.GroupUser,
                attributes: ['user_id', 'nickname']
            }]
        });
        if (!group) {
            return ctx.apiFail('该群聊不存在或者已被封禁');
        }
        let index = group.group_users.findIndex(item => item.user_id === current_user_id);
        if (index === -1) {
            return ctx.apiFail('你不是该群的成员');
        }
        // 组织数据格式
        let from_name = group.group_users[index].nickname;
        let message = {
            id: (new Date()).getTime(), // 唯一id,后端生成唯一id
            from_avatar: ctx.authUser.avatar,// 发送者头像
            from_name: from_name || ctx.authUser.nickname || ctx.authUser.username, // 发送者昵称
            from_id: current_user_id, // 发送者id
            to_id, // 接收人/群 id
            to_name: group.name, // 接收人/群 名称
            to_avatar: group.avatar, // 接收人/群 头像
            chat_type: 'group', // 接收类型
            type,// 消息类型
            data, // 消息内容
            options: {}, // 其他参数
            create_time: (new Date()).getTime(), // 创建时间
            isremove: 0, // 是否撤回
            group: group
        }
        // 视频,截取封面
        if (message.type === 'video') {
            message.options.poster = message.data + '?x-oss-process=video/snapshot,t_10,m_fast,w_300,f_png';
        }
        // 音频,带上音频时长
        if (message.type === 'audio') {
            options = JSON.parse(options);
            message.options.time = options.time || 1;
        }
        // 名片
        if (message.type === 'card') {
            // 验证名片用户是否存在
            message.options = JSON.parse(options)
        }
        // 推送消息
        group.group_users.forEach(item => {
            if (item.user_id !== current_user_id) {
                ctx.sendAndSaveMessage(item.user_id, message);
            }
        });
        ctx.apiSuccess(message);
    }
    // 获取离线消息
    async getmessage() {
        const { ctx, app, service } = this;
        let current_user_id = ctx.authUser.id;
        let key = 'getmessage_' + current_user_id;
        let list = await service.cache.getList(key);
      
        // 清除离线消息
        await service.cache.remove(key);
        // 批量推送
        list.forEach(async (message) => {
            let d = JSON.parse(message);
            ctx.sendAndSaveMessage(current_user_id, d.message, d.msg);
        });
    }
    // 撤回
    async recall() {
        const { ctx, app } = this;
        let current_user_id = ctx.authUser.id;
        ctx.validate({
            to_id: {
                type: 'int',
                required: true,
                desc: '接收人/群id'
            },
            chat_type: {
                type: 'string',
                required: true,
                range: {
                    in: ['user', 'group']
                },
                desc: '接收类型'
            },
            id: {
                type: 'int',
                required: true,
                desc: '消息id'
            }
        });
        let { to_id, chat_type, id } = ctx.request.body;
        let message = {
            from_id: current_user_id,
            to_id,
            chat_type,
            id
        }
        // 单聊
        if (chat_type === 'user') {
            ctx.sendAndSaveMessage(to_id, message, 'recall');
            return ctx.apiSuccess(message);
        }
        // 群聊
        let group = await app.model.Group.findOne({
            where: {
                id: to_id,
                status: 1
            },
            include: [{
                model: app.model.GroupUser,
                attributes: ['user_id']
            }]
        });
        if (group) {
            group.group_users.forEach(item => {
                if (item.user_id !== current_user_id) {
                    ctx.sendAndSaveMessage(item.user_id, message, 'recall');
                }
            });
        }
        return ctx.apiSuccess(message);
    }
}
module.exports = ChatController;

/app/extend/extend.js

// app/extend/context.js
var qr = require('qr-image');
module.exports = {
  // 成功提示
  apiSuccess(data = '', msg = 'ok', code = 200) {
    this.body = { msg, data };
    this.status = code;
  },
  // 失败提示
  apiFail(data = '', msg = 'fail', code = 400) {
    this.body = { msg, data };
    this.status = code;
  },
  // 生成token
  getToken(value) {
        return this.app.jwt.sign(value, this.app.config.jwt.secret);
  },
  // 验证token
  checkToken(token) {
        return this.app.jwt.verify(token, this.app.config.jwt.secret);
  },
  // 发送或者存到消息队列中
  sendAndSaveMessage(to_id,message,msg='ok'){
      const { app,service } = this;
      let current_user_id = this.authUser.id;
       // 拿到当前的socket
    //   let  socket = app.ws.user[to_id];
       // 验证对方是否在线,不在线记录到待接收消息队列中 在线:消息推送 存储到对方的聊天记录中 chatlog_对方用户id_user_当前用户id
            
            if(app.ws.user && app.ws.user[to_id]){
                // 消息推送
                app.ws.user[to_id].send(JSON.stringify({
                    msg,
                    data:message
                }))
                // 存到历史记录中
                if(msg === 'ok'){
                   
                service.cache.setList(`chatlog_${to_id}_${message.chat_type}_${current_user_id}`,message); 
                }
            }else{
                service.cache.setList('getmessage_'+to_id,{
                    message,
                    msg
                });
                
            }
  },
  // 生成二维码
  qrcode(url){
      var img = qr.image(url,{size:10});
      this.response.type = 'image/png';
      this.body = img;
  },
  // 生成唯一id
  genID(length) {
      return Number(Math.random().toString().substr(3, length) + Date.now()).toString(36);
  },
  // 用户上线
  async online(user_id,pid){
      const {app,service} = this;
      // 下线其他设备
      let pid = service.cache.get('online_'+user_id);
      if(pid){
          // 通知对应进程用户下线
          app.messager.sendTo(pid,'offline',user_id);
      }
      // 存储上线状态
      service.cache.set('online_'+user_id,pid);
  }
};

感谢大家观看,我们下次见

目录
相关文章
|
4月前
|
API Android开发
Android P 性能优化:创建APP进程白名单,杀死白名单之外的进程
本文介绍了在Android P系统中通过创建应用进程白名单并杀死白名单之外的进程来优化性能的方法,包括设置权限、获取运行中的APP列表、配置白名单以及在应用启动时杀死非白名单进程的代码实现。
65 1
|
7月前
|
存储 Java Android开发
app应用程序进程启动过程
app应用程序进程启动过程
62 1
|
7月前
|
前端开发 Android开发 iOS开发
应用研发平台EMAS使用 aliyun-react-native-push 库接入推送和辅助通道,推送都可以收到,但是在App切到后台或者杀掉进程之后就收不到推送了,是需要配置什么吗?
【2月更文挑战第31天】应用研发平台EMAS使用 aliyun-react-native-push 库接入推送和辅助通道,推送都可以收到,但是在App切到后台或者杀掉进程之后就收不到推送了,是需要配置什么吗?
126 2
|
7月前
uni-app 187多进程实现(二)
uni-app 187多进程实现(二)
47 3
|
7月前
|
开发工具 Android开发 开发者
oppo和小米在无app进程运行时可以收到推送,但是华为和vivo不行,是华为和vivo需要什么特殊配置吗
【1月更文挑战第21天】【1月更文挑战第101篇】oppo和小米在无app进程运行时可以收到推送,但是华为和vivo不行,是华为和vivo需要什么特殊配置吗
102 1
|
7月前
|
运维 物联网 开发者
蚂蚁集团mPaaS平台与华为达成合作 加速上千家App“鸿蒙化”进程
11月23日,蚂蚁集团数字科技事业群旗下mPaaS与华为举行鸿蒙合作签约仪式,双方宣布将在鸿蒙产业创新、技术应用、商业发展等方面展开深入合作。随着mPaaS完成鸿蒙系统适配,将进一步丰富政务民生应用的国产系统兼容性,使更多伙伴、开发者和用户从中获益,并更好促进移动应用生态的繁荣及移动端体验的升级。
336 0
|
Android开发
Android进程守护,让APP在系统内存中常驻(二)
Android进程守护,让APP在系统内存中常驻
769 0
|
Android开发
Android进程守护,让APP在系统内存中常驻(一)
Android进程守护,让APP在系统内存中常驻
946 0
|
监控 安全 Android开发
【Android 逆向】Android 进程代码注入原理 ( 注入本质 | 静态注入和动态注入 | 静态注入两种方式 | 修改动态库重打包 | 修改 /data/app/xx/libs 动态库 )
【Android 逆向】Android 进程代码注入原理 ( 注入本质 | 静态注入和动态注入 | 静态注入两种方式 | 修改动态库重打包 | 修改 /data/app/xx/libs 动态库 )
534 0