使用ipcMain和ipcRenderer

时间:2019-07-03 12:44:08

标签: node.js design-patterns electron

因为Electron有两个进程,所以我们的javasript代码不是全局的,因此我发现自己发送和接收很多事件(具有很多不同的名称)来执行通常使用同一方法进行回调的操作。
如果我们需要共享一些全局变量(例如全局常量),则情况更糟。

我目前的方法是尝试以网络套接字的方式管理Main和Renderer之间的连接,但是感觉并不好,也许我做错了(我也觉得我陷入了DRY原则,因为我无法创建一个具有ipc的全局事件侦听器,我需要对每个“发送”和每个“开启”的事件名称进行硬编码。)
我正在通过MVC中的视图管理窗口(渲染器过程)。
也许我应该只使用主进程来初始化主窗口,然后从我们的窗口(Renderer)执行所有操作(数据库,外部api调用等)? (也就是说,MVC全部在Renderer进程中,而在Main进程中几乎不执行任何操作?)

从Electron那里解决这两个过程的最佳设计模式是什么?

2 个答案:

答案 0 :(得分:2)

  

如果我们需要共享一些全局变量(例如,   全局常量)。

您可以使用global object

require('electron').remote.getGlobal('sharedObject').someProperty = 'new value'
  

我需要对每个“发送”和每个事件的事件名称进行硬编码   “上”)。

不完全是一种设计模式,但我的解决方案是定义“路由”功能。

渲染器:

function sendMessageToMain(msg) {
    var arg;
    switch (msg) {  
        case "save-project":
            arg = { event: "save-project", sender: "editor", data: editorJson };

            break;
    }    
    ipcRenderer.send('app-message', arg);
 }

主要

ipcMain.on('app-message', (event, arg) => {

    switch (arg.event) {
        case "save-project":
            global.model.data = arg.data;

            switch (arg.sender) {
                case "editor":
                    // do something
                    break;
                case "player":
                    // do something else
                    break;
            }
            break;
       }
}

答案 1 :(得分:0)

    // args = { route : 'some_function_name', ..... }
class ipc{
     constructor() {
        ipcMain.on('data', (event, args) => {
            let route = args.route
            if (this[route]) {    /* it looks given function name if 
                                      exist on class instance */
                this[route](args) // then call it
            } else return
        })
     }
     some_function_name(args){
          // codes
     }
}

关于此的更具体的解决方案

export default class ipcHelper {
    private parse_sender
    constructor() {
        ipcMain.on('data', (event, args) => {
            let route = args['route'] 
            if (this[route]){  // same as before , it look if 
                                      //function if exist in class 
                                          // instance
                this.parse_sender = (function (argsToSend) {
                    if (argsToSend['backToSender'])
                    {
                        event.sender.send('data' , argsToSend)
                    }
                    else return
                }(this[route](args))) /*self caller function
                                       it will call event.sender.send() 
            } 
        })
    }

}

用法

class ipc extends ipcHelper{

      constructor() {
         super()
      }

      some_function_name(args) {
          // do stuffs here
          return let argsToSend = {
                                 backToSender : true, /* if you 
                                 don't want to send any data to 
                                 renderer, you should make it false */
                           // rest of other datas to send renderer
                              }
      }

}