简体   繁体   中英

How do I pass MySQL query results back to renderer from Electron "main" process?

I'm building a React/Electron/MySQL app and am trying to pass the results of my query (in ipcMain) back to the renderer. Here is the basic skeleton:

main.js

ipcMain.handle("testQuery", async (event) => {
  connection.connect(function(err) {
    if(err){throw(err)}
    let sql = "SELECT * FROM `workers`";
    connection.query(sql, function(err, rows, fields) {
      if(err){console.log(err); return}
      console.log("results =", rows);
      connection.end(function(){})
      return rows; // i know this isn't currently returning anywhere useful
    })
  })
})

preload.js

contextBridge.exposeInMainWorld("electronAPI", {
  testQuery: () => ipcRenderer.invoke("testQuery").then((result) => {return result})
})

MyComponent.jsx

async function testQuery() {
  return await window.electronAPI.testQuery()
}

class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {data : "nothing"}
  }

  render() {
    return (
      <button type="button" id="testButton" onClick={() =>
        testQuery((result) => {
          this.setState({data : result})
        })}>Test Query</button>
      <p>{this.state.data}</p>
    )
  }
}

I've tried some approaches found in other threads, like passing a callback through (which didn't work, somewhere the callback got lost). I've also received errors like "object could not be cloned" after getting creative moving things around. If I try to declare a variable in the top scope of ipcMain, and pass the query result to it before passing it back as the "invoke" reply, I get "Cannot enqueue Query after invoking quit." What approach should I be aiming towards? (I'm new to working with Promises, as well.)

I don't have an easy way to test this, but this is how I would adjust your code. I would also do as midnight-coding suggests and read into callbacks vs promises, serialization, etc. Ultimately, you weren't that far off though, Also. I assume the rows arg is an array or objects and has serializable data within it, If it does not. you should process that prior to resolving the promise with that data. Hope this is helpful and best of luck to you!

// main.js
ipcMain.handle("testQuery", 
  (event) => new Promise((resolve, reject) => {
      connection.connect(function(err) {
        if(err){
          reject(err); 
        } else {
          const sql = "SELECT * FROM `workers`";
          connection.query(sql, function(err, rows, fields) {
            if(err){
              console.log(err); 
              reject(err);
            } else {              
              console.log({rows});
              connection.end(function(){});
              resolve(rows); 
            }
          })
        }
      })
    })
)
// preload.js
contextBridge.exposeInMainWorld("electronAPI", {
  testQuery: () => ipcRenderer.invoke("testQuery")
})
// mycomponent.jsx
class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {data : "nothing"};
    this.onClick = this.onClick.bind(this);
  }

  async onClick() {
    try {
      const data = await window.electronAPI.testQuery();
      this.setState({data})
    } catch (error) {
      // handle error
    }            
  }

  render() {
    return (
      <button type="button" id="testButton" onClick={this.onClick}>Test Query</button>
      <p>{this.state.data}</p>
    )
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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