ElectronJS:使用 invoke/handle 时不需要时记录方法会多次触发
ElectronJS: logging method fires multiple times when don't wanted when using invoke/handle
如标题所述。我的 ElectronJS 项目有这个问题。当我尝试从调用的处理程序记录输出时,记录会发生多次,即使函数 运行 只有一次。这可能是什么原因?
函数 运行 只有一次,对于每个 class object 创建。请参阅底部的 GIF 以查看“正在执行的”问题。
我已经尝试删除处理程序和侦听器,但这只会导致下一个 object 无法调用 downloadPoster
..
在此先感谢您的帮助。
下面是 object 是如何实例化和“处理”的。
// On drop
window.ondrop = async function(e) {
e.preventDefault();
body.classList.remove('file-hover');
for (var [i, file] of Object.entries(e.dataTransfer.files)) {
var x = new Movie(file.path);
await x.process();
}
return false;
};
这是 renderer.js
中 class 的函数
/**
* Download poster file for movie
*/
async downloadPoster() {
// This is the url used to search for the poster we want
var searchUrl = new URL(Config.api.searchUrl);
searchUrl.search = new URLSearchParams({
page: 1,
api_key: Config.api.key,
query: this.#movie.tags.title,
year: this.#movie.tags.year
});
// Search for poster in the main thread
await axios.get(searchUrl.href)
.then(async (resp) => {
// No results
if (resp.data.total_results <= 0) {
this.log('No poster found', 'error');
return;
}
// Invoke poster download
const result = await ipcRenderer.invoke('downloadPoster', {
src: Config.api.posterUrl + resp.data.results[0].poster_path,
dest: path.join(this.#movie.new.absolutePath, Config.api.posterFilename)
})
// This shows "undefined"
this.log(result);
})
.catch(async (err) => {
this.log('Could not search for poster: ' + err, 'error');
});
}
这是来自 main.js
的处理函数
// Download poster
ipcMain.handle('downloadPoster', async (event, args) => {
await axios.get(args.src, { responseType: 'stream' })
.then(async (resp) => {
const writeStream = fs.createWriteStream(args.dest);
// Write data to file
await resp.data.pipe(writeStream);
// When finished, send reply back
writeStream.on('finish', async () => {
return {
success: true,
message: 'Poster downloaded'
}
});
// On error writing, send reply back
writeStream.on('error', async (err) => {
return {
success: false,
message: 'Could not write poster to file: ' + err
}
});
})
.catch(async (err) => {
return {
success: false,
message: 'Could not download poster: ' + err
}
});
});
你可能误会了invoke
/handle
。使用该功能的全部意义在于,来自主进程中处理程序的 return 值由渲染器中的调用方法 return 编辑。所以你可以这样做:
// main.js
ipcMain.handle('some-command', async (evt, data) => {
// do something with data, the handler can also be async
const value = await getSomeValue();
return doSomething(data, value);
}
// renderer.js
(async () => {
const invokeReturn = await ipcRenderer.invoke('some-command', data);
// invokeReturn will contain the result of doSomething(data, value) from main
})
我需要对您的代码进行一些调试才能确定,但我的直觉是该行为是由这段代码引起的:
// Poster download reply from the invoke above
ipcRenderer.on('downloadPosterReply', async (event, args) => {
您正在设置侦听器并且永远不会删除它,因此每次函数调用都会添加一个新的处理程序,从而导致出现越来越多的日志。感谢 invoke
/handle
,你根本不需要在这里使用 on
处理程序。
如标题所述。我的 ElectronJS 项目有这个问题。当我尝试从调用的处理程序记录输出时,记录会发生多次,即使函数 运行 只有一次。这可能是什么原因?
函数 运行 只有一次,对于每个 class object 创建。请参阅底部的 GIF 以查看“正在执行的”问题。
我已经尝试删除处理程序和侦听器,但这只会导致下一个 object 无法调用 downloadPoster
..
在此先感谢您的帮助。
下面是 object 是如何实例化和“处理”的。
// On drop
window.ondrop = async function(e) {
e.preventDefault();
body.classList.remove('file-hover');
for (var [i, file] of Object.entries(e.dataTransfer.files)) {
var x = new Movie(file.path);
await x.process();
}
return false;
};
这是 renderer.js
/**
* Download poster file for movie
*/
async downloadPoster() {
// This is the url used to search for the poster we want
var searchUrl = new URL(Config.api.searchUrl);
searchUrl.search = new URLSearchParams({
page: 1,
api_key: Config.api.key,
query: this.#movie.tags.title,
year: this.#movie.tags.year
});
// Search for poster in the main thread
await axios.get(searchUrl.href)
.then(async (resp) => {
// No results
if (resp.data.total_results <= 0) {
this.log('No poster found', 'error');
return;
}
// Invoke poster download
const result = await ipcRenderer.invoke('downloadPoster', {
src: Config.api.posterUrl + resp.data.results[0].poster_path,
dest: path.join(this.#movie.new.absolutePath, Config.api.posterFilename)
})
// This shows "undefined"
this.log(result);
})
.catch(async (err) => {
this.log('Could not search for poster: ' + err, 'error');
});
}
这是来自 main.js
// Download poster
ipcMain.handle('downloadPoster', async (event, args) => {
await axios.get(args.src, { responseType: 'stream' })
.then(async (resp) => {
const writeStream = fs.createWriteStream(args.dest);
// Write data to file
await resp.data.pipe(writeStream);
// When finished, send reply back
writeStream.on('finish', async () => {
return {
success: true,
message: 'Poster downloaded'
}
});
// On error writing, send reply back
writeStream.on('error', async (err) => {
return {
success: false,
message: 'Could not write poster to file: ' + err
}
});
})
.catch(async (err) => {
return {
success: false,
message: 'Could not download poster: ' + err
}
});
});
你可能误会了invoke
/handle
。使用该功能的全部意义在于,来自主进程中处理程序的 return 值由渲染器中的调用方法 return 编辑。所以你可以这样做:
// main.js
ipcMain.handle('some-command', async (evt, data) => {
// do something with data, the handler can also be async
const value = await getSomeValue();
return doSomething(data, value);
}
// renderer.js
(async () => {
const invokeReturn = await ipcRenderer.invoke('some-command', data);
// invokeReturn will contain the result of doSomething(data, value) from main
})
我需要对您的代码进行一些调试才能确定,但我的直觉是该行为是由这段代码引起的:
// Poster download reply from the invoke above
ipcRenderer.on('downloadPosterReply', async (event, args) => {
您正在设置侦听器并且永远不会删除它,因此每次函数调用都会添加一个新的处理程序,从而导致出现越来越多的日志。感谢 invoke
/handle
,你根本不需要在这里使用 on
处理程序。