ipcMain.handle()无法向ipcRenderer.invoke()返回任何值的问题

huangapple go评论66阅读模式
英文:

Issue with ipcMain.handle() not returning any value to ipcRenderer.invoke()

问题

这是与问题相关的3个文件的翻译:

main.ts(不是整个文件):

app.whenReady().then(() => {
  ipcMain.on("set-credentials", (event, args: object) => {
    encryptedCredentials = safeStorage.encryptString(JSON.stringify(args));
  });

  ipcMain.handle("get-credentials", async (event, args: null) => {
    const decryptedCredentials = await JSON.parse(
      safeStorage.decryptString(encryptedCredentials)
    );
    return decryptedCredentials;
  });

  createWindow();
});

preload.ts(整个文件):

import { ipcRenderer, contextBridge } from "electron";

contextBridge.exposeInMainWorld("electronAPI", {
  setStoredCredentials: async (args: object) =>
    await ipcRenderer.send("set-credentials", args),
  getStoredCredentials: () => {
    ipcRenderer.invoke("get-credentials");
  },
});

Login.tsx(不是整个文件):

const setStoredCredentials = async (e: any, service: string) => {
    e.preventDefault();
    window.electronAPI.setStoredCredentials({
      service,
      username: e.target[0].value,
      password: e.target[1].value,
    });
    setTimeout(() => {
      window.electronAPI.getStoredCredentials().then(
        (data: object) => { console.log(data); } //测试

      )
    }, 1000)
  };

(该 Electron 应用程序使用 React)

解决问题时,我尝试使用 ipcMain.onipcRenderer.sendSyncevent.returnValue,但都没有奏效。当前代码会引发以下错误:

caught TypeError: Cannot read properties of undefined (reading 'then')

而我尝试的其他方法要么产生相同的错误,要么返回 undefined 值。

英文:

So, I struggled with this problem for 2 days, looking in the API documentation of Electron.js and various sites and you guys are my last hope:

Here are the 3 files related to the issue:

main.ts (not the entire file):

app.whenReady().then(() => {
  ipcMain.on("set-credentials", (event, args: object) => {
    encryptedCredentials = safeStorage.encryptString(JSON.stringify(args));
  });

  ipcMain.handle("get-credentials", async (event, args: null) => {
    const decryptedCredentials = await JSON.parse(
      safeStorage.decryptString(encryptedCredentials)
    );
    return decryptedCredentials;
  });

  createWindow();
});

preload.ts (entire file):

import { ipcRenderer, contextBridge } from "electron";

contextBridge.exposeInMainWorld("electronAPI", {
  setStoredCredentials: async (args: object) =>
    await ipcRenderer.send("set-credentials", args),
  getStoredCredentials: () => {
    ipcRenderer.invoke("get-credentials");
  },
});

Login.tsx (not the entire file):

const setStoredCredentials = async (e: any, service: string) => {
    e.preventDefault();
    window.electronAPI.setStoredCredentials({
      service,
      username: e.target[0].value,
      password: e.target[1].value,
    });
    setTimeout(() => {
      window.electronAPI.getStoredCredentials().then(
        (data: object) => { console.log(data); } //testing 

      )
    }, 1000)
  };

(the electron app features React)

So to solve the issue I tried using ipcMain.on and ipcRenderer.sendSync with event.returnValue, didn't work either.
I get the following error with the current code:

caught TypeError: Cannot read properties of undefined (reading 'then')
 

and the other methods I tried either gave the same error or an undefined value.

答案1

得分: 3

双向IPC在渲染进程中需要使用async/await。IPC可能会花费一些时间。如果没有async/await,原始调用只会得到一个Promise

尝试在setStoredCredentialsgetStoredCredentials两个函数中都添加await

const setStoredCredentials = async (e: any, service: string) => {
    e.preventDefault();
    await window.electronAPI.setStoredCredentials({
      service,
      username: e.target[0].value,
      password: e.target[1].value,
    });
    setTimeout(() => {
      await window.electronAPI.getStoredCredentials().then(
        (data: object) => { console.log(data); } //测试

      )
    }, 1000)
  };

如果上面的代码有效,可以移除setTimeout

英文:

Two-way IPC needs async/await in the renderer process. IPC may spend a bit time. Without async/await, the original call just gets a Promise.

Try to add await to both setStoredCredentials and getStoredCredentials.

const setStoredCredentials = async (e: any, service: string) => {
    e.preventDefault();
    await window.electronAPI.setStoredCredentials({
      service,
      username: e.target[0].value,
      password: e.target[1].value,
    });
    setTimeout(() => {
      await window.electronAPI.getStoredCredentials().then(
        (data: object) => { console.log(data); } //testing 

      )
    }, 1000)
  };

If the code above works, setTimeout can be removed.

答案2

得分: 0

当我在 main.ts 中在返回之前使用 console.log() 打印要返回的值时,它正常工作。

另外,cryptedCredentials 变量声明如下:let cryptedCredentials: Buffer;

英文:

just a small clarification:

when I do a console.log() of the value to return in main.ts before returning it it works just fine.

Also the cryptedCredentials var is declared as follows: let cryptedCredentials: Buffer;

huangapple
  • 本文由 发表于 2023年7月20日 18:30:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76728966.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定