electron ipcRenderer.on不是函数

euoag5mw  于 2022-12-08  发布在  Electron
关注(0)|答案(4)|浏览(601)

我正在使用**MainPreloadRenderer**进程堆栈。

preload.js的名称

const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('ipcRenderer', ipcRenderer)

renderer.js的名称

console.log(ipcRenderer) // it shows something like:
/**
{_events: {…}, _eventsCount: 0, _maxListeners: undefined, send: ƒ, sendSync: ƒ, …}
invoke: ƒ ()
postMessage: ƒ ()
send: ƒ ()
sendSync: ƒ ()
sendTo: ƒ ()
sendToHost: ƒ ()
Symbol(kCapture): false
_events: {}
_eventsCount: 0
_maxListeners: undefined
__proto__: Object
**/

console.log(ipcRenderer.on) // undefined

当尝试使用ipcRenderer.on()方法时,它会记录错误:

Uncaught TypeError: ipcRenderer.on is not a function

这个方法在更新的版本中被删除了吗?是什么导致它在渲染器进程中不可用?

5ktev3wc

5ktev3wc1#

这里有一个小的变通办法。但我不认为这是一个安全的好主意。

const { contextBridge, ipcRenderer } = require("electron");    
contextBridge.exposeInMainWorld("electron", { ipcRenderer: { ...ipcRenderer, on: ipcRenderer.on } });
xxls0lw8

xxls0lw82#

正如ipcRenderer的电子API文档所述,“ipcRenderer模块是一个EventEmitter”。
Electron引用的这个“EventEmitter”是node.js的EventEmitter类。Electron的ipcRenderer模块继承了节点的EventEmitter类。
console.log(ipcRenderer)可以查看的方法是Electron的方法。所有继承的方法都可以在Prototype对象中找到,这正是您可以找到on()方法的地方。
要查看这一点,请将console.log(ipcRenderer)添加到一个典型的、格式良好的、安全且可读的preload.js脚本中。
preload.js(主线程)

// Import the necessary Electron components.
const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;

// White-listed channels.
const ipc = {
    'render': {
        // From render to main.
        'send': [],
        // From main to render.
        'receive': [],
        // From render to main and back again.
        'sendReceive': []
    }
};

// Exposed protected methods in the render process.
contextBridge.exposeInMainWorld(
    // Allowed 'ipcRenderer' methods.
    'ipcRender', {
        // From render to main.
        send: (channel, args) => {
            let validChannels = ipc.render.send;
            if (validChannels.includes(channel)) {
                ipcRenderer.send(channel, args);
            }
        },
        // From main to render.
        receive: (channel, listener) => {
            let validChannels = ipc.render.receive;
            if (validChannels.includes(channel)) {

                // Show me the prototype (use DevTools in the render thread)
                console.log(ipcRenderer);

                // Deliberately strip event as it includes `sender`.
                ipcRenderer.on(channel, (event, ...args) => listener(...args));
            }
        },
        // From render to main and back again.
        invoke: (channel, args) => {
            let validChannels = ipc.render.sendReceive;
            if (validChannels.includes(channel)) {
                return ipcRenderer.invoke(channel, args);
            }
        }
    }
);

现在,打开Chrome的DevTools并查看Console选项卡。
Chrome DevTools - Console Tab Output(渲染线程)

v EventEmitter
  > invoke: async ƒ (e,...t)
  > postMessage: ƒ (e,t,n)
  > send: ƒ (e,...t)
  > sendSync: ƒ (e,...t)
  > sendTo: ƒ (e,t,...n)
  > sendToHost: ƒ (e,...t)
  > _events: {app:versions: ƒ}
    _eventsCount: 1
    _maxListeners: undefined
    Symbol(kCapture): false
  v [[Prototype]]: Object
    > addListener: ƒ addListener(type, listener)
    > emit: ƒ emit(type, ...args)
    > eventNames: ƒ eventNames()
    > getMaxListeners: ƒ getMaxListeners()
    > listenerCount: ƒ listenerCount(type)
    > listeners: ƒ listeners(type)
    > off: ƒ removeListener(type, listener)
    v on: ƒ addListener(type, listener)        // <-- Here it is
        length: 2
        name: "addListener"
      > prototype: {constructor: ƒ}
        arguments: (...)
        caller: (...)
        [[FunctionLocation]]: VM14 node:events:486
        [[Prototype]]: ƒ ()
        [[Scopes]]: Scopes[2]
    > once: ƒ once(type, listener)
    > prependListener: ƒ prependListener(type, listener)
    > prependOnceListener: ƒ prependOnceListener(type, listener)
    > rawListeners: ƒ rawListeners(type)
    > removeAllListeners: ƒ removeAllListeners(type)
    > removeListener: ƒ removeListener(type, listener)
    > setMaxListeners: ƒ setMaxListeners(n)
      _events: undefined
      _eventsCount: 0
      _maxListeners: undefined
    > constructor: ƒ EventEmitter(opts)
      Symbol(kCapture): false
    > [[Prototype]]: Object
enyaitl3

enyaitl33#

这里有一个小的变通办法。

// preload.ts
contextBridge.exposeInMainWorld('_Electron_Event_Listener_', {
    onCreateBrowserView,
})

function onCreateBrowserView(listener: (event: IpcRendererEvent, ...args: any[]) => void) {
    ipcRenderer.removeAllListeners('/browserView/create')
    ipcRenderer.on('/browserView/create', listener)
}
dxpyg8gm

dxpyg8gm4#

这是解决这个问题的一个好方法。

const { contextBridge, ipcRenderer } = require("electron");

contextBridge.exposeInMainWorld("electron", {
  ipcRenderer: {
    ...ipcRenderer,
    on: ipcRenderer.on.bind(ipcRenderer),
    removeListener: ipcRenderer.removeListener.bind(ipcRenderer),
  },
});

相关问题