
本文档旨在指导开发者如何从 NAPI (Node.js Addon API) 后端向 Electron 应用发送请求或消息。文章将介绍如何利用 Promise 和回调函数,实现 NAPI 模块与 Electron 主进程之间的通信,并提供详细的代码示例和步骤说明,帮助开发者构建更高效、更灵活的 Electron 应用。
核心问题是如何在 NAPI 模块中触发 Electron 主进程中的事件或函数,以便将数据从后端传递到前端。通常,NAPI 函数会返回一个值,但这并不总是满足需求,尤其是在需要异步地将数据推送到 Electron 应用时。
最直接的方式是利用 Promise。Electron 的 ipcMain.handle 函数允许你注册一个可以被渲染进程调用的异步函数。NAPI 模块可以通过返回一个 Promise,将结果传递给 Electron 主进程。
示例:
假设你有一个 NAPI 函数 SimpleFunction,它接收一个索引,并需要将处理结果发送回 Electron。
scripts.js (渲染进程):
function ClickButtonEvent(currentID) {
api.SimpleFunction(parseInt(currentID)).then((data) => {
// 处理从 NAPI 返回的数据
console.log("Received data from NAPI:", data);
});
}main.js (主进程):
const { app, BrowserWindow, Menu, ipcMain, dialog } = require('electron');
const path = require('path');
const getPcapData = require('./NAPI/build/Release/operations');
function createWindow() {
const 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) => {
const result = await getPcapData.SimpleFunction(index);
return result;
});
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit();
});preload.js (预加载脚本):
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('api', {
SimpleFunction: async (index) => {
return await ipcRenderer.invoke('SimpleFunction', index);
}
});operations.cc (NAPI 模块):
#include <node_api.h>
#include <iostream>
#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_value SimpleFunction(napi_env env, napi_callback_info info) {
napi_deferred deferred;
napi_value promise;
NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
int index = 0;
NAPI_CALL(env, napi_get_value_int32(env, args[0], &index));
// 模拟异步操作
// 在实际应用中,这里会是你的后端代码
// 这里使用一个简单的定时器来模拟异步操作
std::thread([env, deferred, index]() {
// 模拟一些计算
int result = index * 2;
// 创建一个 NAPI 数字对象
napi_value napi_result;
NAPI_CALL(env, napi_create_number(env, result, &napi_result));
// 使用 napi_resolve_deferred 来解决 Promise
NAPI_CALL(env, napi_resolve_deferred(env, deferred, napi_result));
}).detach();
return promise;
}
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);在这个例子中,SimpleFunction 创建了一个 Promise,并在一个单独的线程中模拟了一个异步操作。操作完成后,使用 napi_resolve_deferred 来解决 Promise,并将结果传递给 Electron 主进程。
另一种方法是使用回调函数。你可以在 JavaScript 中定义一个函数,并将其作为参数传递给 NAPI 函数。NAPI 函数在完成操作后,调用这个回调函数。
示例:
scripts.js (渲染进程):
function ClickButtonEvent(currentID) {
api.SimpleFunction(parseInt(currentID), (data) => {
// 处理从 NAPI 返回的数据
console.log("Received data from NAPI via callback:", data);
});
}preload.js (预加载脚本):
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('api', {
SimpleFunction: (index, callback) => ipcRenderer.invoke('SimpleFunction', index).then(callback)
});main.js (主进程):
const { app, BrowserWindow, Menu, ipcMain, dialog } = require('electron');
const path = require('path');
const getPcapData = require('./NAPI/build/Release/operations');
function createWindow() {
const 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) => {
const result = await getPcapData.SimpleFunction(index);
return result;
});
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit();
});operations.cc (NAPI 模块):
#include <node_api.h>
#include <iostream>
#include <thread>
#include <chrono>
#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_value SimpleFunction(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
int index = 0;
NAPI_CALL(env, napi_get_value_int32(env, args[0], &index));
// 模拟一些计算
int result = index * 2;
return nullptr;
}
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);注意事项:
通过使用 Promise 或回调函数,可以方便地从 NAPI 模块向 Electron 应用发送消息。选择哪种方法取决于你的具体需求。Promise 更适合处理异步操作,而回调函数更适合简单的事件通知。理解这两种方法,并根据你的应用场景选择合适的方法,可以帮助你构建更高效、更灵活的 Electron 应用。
以上就是从 NAPI 后端向 Electron 发送请求的完整指南的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号