简体   繁体   English

Node.js 从异步函数返回一个值 - Electron

[英]Node.js Returning a value from an async function - Electron

I am creating a project where I need to take a user input - pass it through a function and return the new value to the user - seems simple enough.我正在创建一个项目,我需要在其中接受用户输入 - 通过函数将其传递并将新值返回给用户 - 看起来很简单。 I am new to async functions and have read everything I possibly can, and can't works out if there's a more fundamental issue I am missing.我是异步函数的新手,并且已经阅读了我可能阅读的所有内容,如果我遗漏了一个更基本的问题,我将无法解决。 I will show the basic code, and then what I wish to achieve.我将展示基本代码,然后是我希望实现的目标。 I believe the issue, is that I am returning back the status of the function rather than the value, but just can't work it out.我认为问题在于我返回的是函数的状态而不是值,但就是无法解决。

Basic Code:基本代码:

ipcMain.on('gpt3', (event, args) => {
    async function gpt3(args) {
        generateResponse('james', 'hello world'); // Takes a user's name & input and recieves a response from a python file.
        event.reply('textRecieve', 'hello world'); // Sends 'Hello World' to the user (ipcRenderer 'textRecieve')
    }
    
    gpt3(args);

})

async function generateResponse(name, text) {
    let testshell = new PythonShell('./python/text_echo.py', { mode: 'text', args: [name, text]});
    let content = "";
    try {
      testshell.on('message', function (message) {
        console.log(message); // prints the output from the python file 'Python File: james Text: hello world'
        return message; // attempting to return the 'Message' from the python file
      });
    } catch (error) {
      console.log("You've f*cked it somewhere my friend");
      console.log(error);
    } 
}

Python Script: Python脚本:

import sys

name = sys.argv[1]
text = sys.argv[2]

print(f'Python File: {name} Text: {text}')
sys.stdout.flush()

Returns: (as expected)回报:(如预期)

> Executing task: npm run start <


> electron-quick-start@1.0.0 start
> electron .

Python File: james Text: hello world

What I'd Like it to do:我想要它做什么:

ipcMain.on('gpt3', (event, args) => {
    async function gpt3(args) {
        message = generateResponse('james', 'hello world'); // Takes a user's name & input and recieves a response from a python file, retunring the message to the 'message' variable.
        console.log(message);
        event.reply('textRecieve', 'message would send here'); // Sends the 'Message' to the user (ipcRenderer 'textRecieve')
    }

    gpt3(args);

  })


async function generateResponse(name, text) {
  let testshell = new PythonShell('./python/text_echo.py', { mode: 'text', args: [name, text]});
  let content = ""
  try {
    testshell.on('message', function (message) {
      console.log(message); // prints the output from the python file 'Python File: james Text: hello world'
      return message; // attempting to return the 'Message' from the python file
    });
  } catch (error) {
    console.log("You've f*cked it somewhere my friend")
    console.log(error)
  } 
  return content; // content needs to be message instead due to async nature it returns empty string
}

Returns:回报:

> Executing task: npm run start <


> electron-quick-start@1.0.0 start
> electron .

Promise { '' }
Python File: james Text: hello world

TLDR; TLDR; I would like to take the 'message' generated through 'generateResponse()' and pass it through to my 'event.reply()'.我想将通过“generateResponse()”生成的“消息”传递给我的“event.reply()”。 Instead, I am receiving what I believe to be the status of the Promise.相反,我收到了我认为是 Promise 的状态。 Any help would be greatly appreciated.任何帮助将不胜感激。 Thanks谢谢

You should resolve the promise first.您应该首先解决承诺。

ipcMain.on('gpt3', (event, args) => {
    async function gpt3(args) {
        const message = await generateResponse('james', 'hello world'); 
        console.log(message);
        event.reply('textRecieve', 'message would send here'); // Sends the 'Message' to the user (ipcRenderer 'textRecieve')
    }

    gpt3(args);

  })


async function generateResponse(name, text) {
  let testshell = new PythonShell('./python/text_echo.py', { mode: 'text', args: [name, text]});
  let content = ""
  try {
    testshell.on('message', function (message) {
      console.log(message); // prints the output from the python file 'Python File: james Text: hello world'
      content = message;
    });
  } catch (error) {
    console.log("You've f*cked it somewhere my friend")
    console.log(error)
  } 
  return content; // content needs to be message instead due to async nature it returns empty string
}

Okay, so there were a few problems here... but the main was node.js 'non-ability' to pass variables around when 'asynchronous'.好的,所以这里有一些问题......但主要是 node.js 在“异步”时“无法”传递变量。 with node.js being new to me, I can't lie and say I was confused. node.js 对我来说是新手,我不能撒谎说我很困惑。 Hopefully, the following link to a great workaround/method and my working code will be able to help someone:希望以下指向一个很好的解决方法/方法的链接以及我的工作代码能够帮助某人:

https://stackoverflow.com/a/23667087/10246221 https://stackoverflow.com/a/23667087/10246221

Code: ipcMain - nested within app.whenReady().代码: ipcMain -嵌套在 app.whenReady() 中。

ipcMain.on('gpt3', (event, input) => {
    gpt3Async(event, input, function(result) { 
      event.reply('textRecieve', result);
      console.log('gpt3Async: '+ result);
      })

  })

Code: Generic 'nested' Function - free-floating around 'main.js' or 'index.js'.代码:通用“嵌套”函数-围绕“main.js”或“index.js”自由浮动。

function gpt3Async(event, input, callback) {
    console.log('input: ' + input)
    let testshell = new PythonShell('./python/text_echo.py', { mode: 'text', args: ['elliott' ,input]});
    testshell.on('message', function (message) {
      callback(message);
    });
}

Code: Python Script 'text_echo.py' - in my case within a 'python' subdirectory.代码: Python 脚本 'text_echo.py' -在我的例子中是在一个 'python' 子目录中。

import sys

name = sys.argv[1]
text = sys.argv[2]

print(f'Python File: {name} Text: {text}')
#sys.stdout.flush()
sys.stdout.flush()

For anyone working on a project where you need input and output for python scripts, this will help you out.对于从事需要 Python 脚本输入和输出的项目的任何人,这将为您提供帮助。 also make sure you turn on the following:还要确保打开以下内容:

webPreferences: {
      //preload: path.join(__dirname, 'preload.js'),
      nodeIntegration: true,
      contextIsolation: false,
      enableRemoteModule: true,
      sandbox: false,
    }, 

BUT!, please be aware of the security implications this will have on your code , More info is available here: https://stackoverflow.com/a/57507392 & https://electronjs.org/docs/tutorial/security#3-enable-context-isolation-for-remote-content & much more so do some reading if this is an important project...但是!,请注意这将对您的代码产生的安全影响,更多信息可在此处获得: https ://stackoverflow.com/a/57507392 & https://electronjs.org/docs/tutorial/security#3 -enable-context-isolation-for-remote-content等等,如果这是一个重要的项目,请阅读更多内容......

Okay, An explainer, or at least something that blew my mind as a beginner... .好吧,一个解释器,或者至少让我作为初学者大吃一惊的东西...... The way I finally understood it was through the example link:我最终理解它的方式是通过示例链接: 来自其他 SO 用户的示例代码截图 https://stackoverflow.com/a/23667087/10246221 https://stackoverflow.com/a/23667087/10246221

for some reason, it hadn't clicked with me that functions could be nested within functions like this, all in one line.出于某种原因,我没有想到函数可以嵌套在这样的函数中,全部在一行中。 For someone who is used to JS or node.js this may seem fundamental, but seeing as this is a first-time project to me, and maybe others - if still using python code.对于习惯 JS 或 node.js 的人来说,这可能看起来很基础,但对于我和其他人来说这是第一次项目——如果仍然使用 python 代码。 Hopefully, this may help!希望这可能会有所帮助!

ipcMain.on('gpt3', (event, input) => { gpt3Async(event, input, function(result) { event.reply('textRecieve', result); console.log('gpt3Async: '+ result);})})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM