您好,在参考electron-trpc的示例代码:(做事件订阅/事件触发)的时候:
https://github.com/jsonnull/electron-trpc/blob/main/examples/basic-react/electron/api.ts
代码如下:
import z from 'zod';
import { initTRPC } from '@trpc/server';
import { observable } from '@trpc/server/observable';
import { EventEmitter } from 'events';
const ee = new EventEmitter();
const t = initTRPC.create({ isServer: true });
export const router = t.router({
greeting: t.procedure.input(z.object({ name: z.string() })).query((req) => {
const { input } = req;
ee.emit('greeting', `Greeted ${input.name}`);
return {
text: `Hello ${input.name}` as const,
};
}),
subscription: t.procedure.subscription(() => {
return observable((emit) => {
function onGreet(text: string) {
emit.next({ text });
}
ee.on('greeting', onGreet);
return () => {
ee.off('greeting', onGreet);
};
});
}),
});
export type AppRouter = typeof router;
请问下,应该如何使用呢?
1、在主进程如何使用(订阅和触发)?
2、在渲染进程如何使用(订阅和触发)?
创建一个新的项目文件夹,并在其中创建以下文件和文件夹结构:
my-electron-trpc-app/
├── main.ts
├── preload.ts
├── renderer.ts
├── package.json
├── tsconfig.json
└── webpack.config.js
在项目根目录下运行以下命令来安装必要的依赖:
npm init -y
npm install electron @trpc/server @trpc/client electron-trpc zod typescript ts-loader webpack webpack-cli
在项目根目录下创建 tsconfig.json 文件,并添加以下内容:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./dist"
},
"include": ["./**/*.ts"]
}
在项目根目录下创建 webpack.config.js 文件,并添加以下内容:
const path = require('path');
module.exports = {
entry: {
main: './main.ts',
preload: './preload.ts',
renderer: './renderer.ts',
},
target: 'electron-main',
module: {
rules: [
{
test: /\.ts$/,
include: /src/,
use: [{ loader: 'ts-loader' }],
},
],
},
resolve: {
extensions: ['.ts', '.js'],
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
};
package.json
"scripts": {
"start": "webpack && electron ."
}
import { app, BrowserWindow } from 'electron';
import { createIPCHandler } from 'electron-trpc/main';
import { initTRPC } from '@trpc/server';
import { observable } from '@trpc/server/observable';
import { EventEmitter } from 'events';
import { z } from 'zod';
const ee = new EventEmitter();
const t = initTRPC.create({ isServer: true });
export const router = t.router({
greeting: t.procedure.input(z.object({ name: z.string() })).query((req) => {
const { input } = req;
ee.emit('greeting', `Greeted ${input.name}`);
return { text: `Hello ${input.name}` };
}),
subscription: t.procedure.subscription(() => {
return observable((emit) => {
function onGreet(text: string) {
emit.next({ text });
}
ee.on('greeting', onGreet);
return () => {
ee.off('greeting', onGreet);
};
});
}),
});
app.on('ready', () => {
const win = new BrowserWindow({
webPreferences: {
preload: 'path/to/preload.js',
},
});
createIPCHandler({ router, windows: [win] });
// 示例:在主进程中触发事件
setTimeout(() => {
ee.emit('greeting', 'Hello from main process');
}, 5000); // 5秒后触发事件
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
import { exposeElectronTRPC } from 'electron-trpc/main';
process.once('loaded', async () => {
exposeElectronTRPC();
});
import { createTRPCProxyClient } from '@trpc/client';
import { ipcLink } from 'electron-trpc/renderer';
export const client = createTRPCProxyClient({
links: [ipcLink()],
});
// 触发事件
client.greeting({ name: 'YourName' }).then(response => {
console.log(response.text); // 输出: Hello YourName
});
// 订阅事件
client.subscription('subscription', {
next(data) {
console.log(data.text);
},
error(err) {
console.error('Subscription error:', err);
},
});
在项目根目录下运行以下命令来构建并启动 Electron 应用:
npm start
在主进程中,你需要通过 electron-trpc
提供的 API 来订阅事件和触发事件。以下是如何在主进程中实现这些功能的示例:
订阅事件:
const { createClient } = require('@trpc/client');
const { app, BrowserWindow } = require('electron');
const path = require('path');
let mainWindow;
function createWindow() {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
enableRemoteModule: false,
nodeIntegration: false,
},
});
mainWindow.loadFile('index.html');
// Create TRPC client
const trpcClient = createClient({
url: 'http://localhost:3000/api', // 替换为你的 TRPC 服务器 URL
});
// 订阅事件
const subscription = trpcClient.subscription.subscription({});
subscription.subscribe({
next: (data) => {
console.log('Received greeting:', data.text);
},
error: (err) => {
console.error('Subscription error:', err);
},
complete: () => {
console.log('Subscription completed');
},
});
}
app.on('ready', createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
// 触发事件
const ee = require('events').EventEmitter;
const eventEmitter = new ee();
// 在适当的地方(例如响应某个操作)
eventEmitter.emit('greeting', 'John Doe');
注意:这里的 eventEmitter.emit('greeting', 'John Doe');
是为了模拟触发事件,但在实际场景中,你应该使用你的 TRPC 服务器中的 ee.emit('greeting', ...)
来触发事件。
在渲染进程中,由于 Electron 的安全策略,直接访问主进程的 EventEmitter
实例是不可能的。你应该通过 ipcRenderer
与主进程通信,然后在主进程中处理这些请求。
在渲染进程中订阅事件:
你可以通过 preload.js
文件来暴露一个接口给渲染进程,以便订阅和触发事件。但是,由于 TRPC 已经处理了 API 的路由,你通常会在渲染进程中直接使用 TRPC 客户端来订阅事件。
// 渲染进程中的 JavaScript (例如:renderer.js)
const { createClient } = require('@trpc/client/react');
const trpcClient = createClient({
url: 'http://localhost:3000/api', // 替换为你的 TRPC 服务器 URL
});
function useGreetingSubscription() {
const subscription = trpcClient.subscription.subscription({});
return React.useMemo(() => {
const [data, setData] = React.useState(null);
const [error, setError] = React.useState(null);
React.useEffect(() => {
const unsubscribe = subscription.subscribe({
next: (res) => setData(res),
error: (err) => setError(err),
});
return () => unsubscribe();
}, [subscription]);
return { data, error };
}, [subscription]);
}
function App() {
const { data, error } = useGreetingSubscription();
if (error) {
return <div>Error: {error.message}</div>;
}
return (
<div>
{data && <div>Received greeting: {data.text}</div>}
</div>
);
}
export default App;
在渲染进程中触发事件:
由于安全原因,渲染进程不应该直接触发主进程中的事件。相反,你应该通过 ipcRenderer
发送一个消息到主进程,然后让主进程处理这个请求并触发相应的事件。但是,在这个场景中,由于你已经在使用 TRPC,你应该通过 TRPC 的 greeting
过程来触发事件,而不是直接操作 EventEmitter
。
// 渲染进程中的 JavaScript (例如:通过某个按钮触发)
async function triggerGreeting() {
try {
const res = await trpcClient.query('greeting', { name: 'John Doe' });
console.log('Greeting response:', res);
} catch (err) {
console.error('Error triggering greeting:', err);
}
}
// 例如,在某个按钮点击事件中调用 triggerGreeting()
在这个例子中,当 triggerGreeting
函数被调用时,它会通过 TRPC 服务器触发 greeting
事件,然后订阅这个事件的客户端(无论是在主进程还是渲染进程)都会收到这个事件并处理它。
Node.js应用程序可以使用composer-client.BusinessNetworkConnection.onAPI调用从业务网络订阅事件。事件在业务网络模型文件中定义,并由交易处理函数文件中的指定交易处理。有关发布事件的更多信息,请参阅发布事件。 在你开始之前 在应用程序可以订阅事件之前,你必须定义一些事件和发送它们的交易。还必须部署业务网络,并且必须具有可连接到该业务网络的连接配置文件
我在WPF中编写代码,其中有两个视图模型。在一个视图模型中,我正在关闭一个prism弹出窗口,在关闭时,我将调用我的发布方法,如: 而我的subscribe事件如下所示: 以下是这两个类接收事件聚合器的方式: 这是我的第二堂课: 每次取消交互时,发布都会被发布,但不会被调用,因为订阅。 在具有subscribe方法的其他类之前被调用。会有问题吗?我只想在交互完成时初始化我的集合视图,而不破坏MVV
基本上,我试图使用ARM部署一个事件网格订阅来收集订阅中的特定事件(主题类型= Azure订阅)。我已经有一个创建了事件网格触发功能的功能应用程序,只需要将该功能与事件网格订阅绑定为webhook。 我正在使用Azure DevOps中的发布管道来自动化整个工作流。 以下是我使用的一个示例: 这最终部署了事件网格主题,而不是事件网格订阅。 然后,有人建议我尝试以下操作: 但是这最终以这个错误而失败
问题内容: 我的整个项目都使用(Bluebird)Promises,但是有一个使用EventEmitter的特定库。 我想要实现以下目标: 我在Promises链中读了EventEmitter的答案。这给了我一种执行’connect’事件的回调的方法。这是我到目前为止所到之处 现在如何进一步链接“ eventB”? 问题答案: 我假设您想为每个事件做不同的事情。即使由的动作触发,您也可以将其视为另
本文向大家介绍JS代码触发事件代码实例,包括了JS代码触发事件代码实例的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了js代码触发事件代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。
我编写了一个Spring RestController,它返回一个SseEmitter(对于服务器发送的事件),并向每个事件添加HATEOAS链接。以下是该控制器的一个简化但有效的示例: 问候语课程如下: 此代码运行完美。如果我尝试使用Web浏览器访问REST服务,我会看到显示正确内容和链接的事件。 结果如下所示(每个事件出现在前一个事件之后5秒): 现在我需要调用这个REST服务并从另一个Spr
Tendermint 会发出不同的事件,您可以通过Websocket订阅这些事件。这对于第三方应用程序(如 analysys)或检查状态非常有用。 事件列表 您可以通过 Websocket 调用 subscribe RPC 方法订阅上面的任何事件。 { "jsonrpc": "2.0", "method": "subscribe", "id": "0", "para
调用: myContract.events.allEvents([options][, callback]) 与events相同,只是可以接收合约的全部事件。可以使用options.filter属性进行过滤。