You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从NAPI后端向Electron主动发送数据?附代码示例

解决方案:NAPI主动向Electron发送数据

核心思路

通过传递回调函数给NAPI,让NAPI在需要主动发送数据时调用该回调,再由Electron主进程将数据转发给渲染进程。


代码修改步骤

1. 主进程文件(main.js)

保存窗口实例,并修改SimpleFunction的IPC处理逻辑,将回调传递给NAPI:

const { app, BrowserWindow, Menu, ipcMain, dialog } = require('electron');
const path = require('path');
const getPcapData = require('./NAPI/build/Release/operations');

let win; // 全局保存窗口实例,用于向渲染进程发消息

function createWindow() {
  win = new BrowserWindow({
    width: 1920,
    height: 1080,
    minWidth: 500,
    minHeight: 500,
    maxWidth: 1920,
    maxHeight: 1080,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
    },
  });

  win.loadFile('src/HTML/index.html');
}

app.whenReady().then(() => {
  createWindow();

  ipcMain.handle('SimpleFunction', async (event, index) => {
    // 定义回调函数,接收NAPI传来的数据并转发给渲染进程
    const sendCallback = (data) => {
      win.webContents.send('napi-data', data);
    };
    // 将业务参数和回调传给NAPI
    getPcapData.SimpleFunction(index, sendCallback);
    return 'NAPI任务已启动'; // 返回调用状态,而非业务数据
  });
});

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});

2. 预加载文件(preload.js)

新增暴露监听NAPI数据的方法,保证渲染进程安全接收消息:

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

contextBridge.exposeInMainWorld('api', {
  SimpleFunction: async (index) => {
    return await ipcRenderer.invoke('SimpleFunction', index);
  },
  // 暴露监听NAPI主动推送数据的方法
  onNapiData: (callback) => {
    ipcRenderer.on('napi-data', (event, data) => callback(data));
  }
});

3. 前端调用文件(scripts.js)

先注册消息监听,再触发NAPI调用,确保不会错过数据:

// 提前注册监听,接收NAPI主动发送的数据
api.onNapiData((data) => {
  console.log('收到NAPI数据:', data);
  // 此处编写业务逻辑,比如更新页面UI、处理数据等
});

async function ClickButtonEvent(currentID) {
  const result = await api.SimpleFunction(parseInt(currentID));
  console.log(result); // 输出"NAPI任务已启动"
}

4. NAPI文件(operations.cc)

修改SimpleFunction接收回调参数,并在SendToElectron中调用回调传递数据:

#include <node_api.h>
#include <iostream>
#include <cstdio>

#define NAPI_CALL(env, call)                                      
  do                                                              
  {                                                               
    napi_status status = (call);                                  
    if (status != napi_ok)                                        
    {                                                             
      const napi_extended_error_info *error_info = NULL;          
      napi_get_last_error_info((env), &error_info);               
      bool is_pending;                                            
      napi_is_exception_pending((env), &is_pending);              
      if (!is_pending)                                            
      {                                                           
        const char *message = (error_info->error_message == NULL) 
                                  ? "empty error message"         
                                  : error_info->error_message;    
        napi_throw_error((env), NULL, message);                   
        return NULL;                                              
      }                                                           
    }                                                             
  } while (0)

// 保存NAPI环境和回调函数(若需支持多并发,建议改用结构体封装)
napi_env g_env;
napi_value g_callback;

void SendToElectron(int index) {
  // 示例:构造要发送的数据
  char data_buffer[64];
  sprintf(data_buffer, "NAPI主动推送:ID=%d的处理结果", index);
  
  // 将C字符串转为NAPI字符串
  napi_value napi_data;
  NAPI_CALL(g_env, napi_create_string_utf8(g_env, data_buffer, NAPI_AUTO_LENGTH, &napi_data));

  // 调用回调函数,将数据传递给Electron主进程
  napi_value undefined;
  NAPI_CALL(g_env, napi_get_undefined(g_env, &undefined));
  napi_value args[1] = {napi_data};
  NAPI_CALL(g_env, napi_call_function(g_env, undefined, g_callback, 1, args, NULL));
}

napi_value SimpleFunction(napi_env env, napi_callback_info info) {
  size_t argc = 2; // 现在接收两个参数:业务ID、回调函数
  napi_value args[2];
  int index = 0;

  // 获取传入的参数
  NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));

  // 转换业务ID为C++整数
  NAPI_CALL(env, napi_get_value_int32(env, args[0], &index));

  // 保存NAPI环境和回调函数,供SendToElectron使用
  g_env = env;
  g_callback = args[1];

  // 触发主动发送数据的逻辑
  SendToElectron(index);

  // 返回undefined给Electron主进程
  napi_value undefined;
  NAPI_CALL(env, napi_get_undefined(env, &undefined));
  return undefined;
}

napi_value init(napi_env env, napi_value exports) {
  napi_value simpleFunction;
  napi_create_function(env, nullptr, 0, SimpleFunction, nullptr, &simpleFunction);
  napi_set_named_property(env, exports, "SimpleFunction", simpleFunction);
  return exports;
}

NAPI_MODULE(NODE_GYP_MODULE_NAME, init);

关键注意事项

  • 全局变量g_env和g_callback仅适用于单实例场景,若需支持多并发请求,建议将回调和环境封装到结构体中,通过参数传递给SendToElectron;
  • NAPI中传递的数据类型需与Electron侧兼容,若需发送复杂数据(如JSON对象),可在NAPI中构造对应的napi_value对象;
  • 渲染进程需提前注册监听,避免NAPI发送消息时前端未准备好接收。

内容的提问来源于stack exchange,提问作者alx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 00:33:16