gpt4 book ai didi

node.js - Electron/NodeJS 和应用程序在 setInterval/async 代码上卡住

转载 作者:太空宇宙 更新时间:2023-11-03 23:28:30 25 4
gpt4 key购买 nike

我正在开发 electron应用程序使用 Electron API 每 3 秒执行一次屏幕截图捕获,并将其写入给定的目标路径。我设置了一个单独的 BrowserWindow,其中捕获代码在 setInterval() “循环”中运行(请参阅下面的代码结构),但每当捕获发生时,应用程序就会卡住一会儿。我认为这是对文件 ScreenCapturer.jshtml.js 中的 source.thumbnail.toPng()writeScreenshot() 方法的调用。

我设置了这个结构,因为我认为这是要走的路,但显然事实并非如此。 WebWorkers 也不会帮助我,因为我需要 Node 模块,例如 fs、path 和 DesktopCapturer(来自 Electron)。

如何在每次间隔代码(如文件 ScreenCapturer.jshtml.js 中所示)运行时阻塞主线程的情况下执行此类任务(因为我认为渲染器进程是单独的进程?)

<小时/>

我的代码作为引用

ma​​in.js(主进程)

// all the imports and other
// will only show the import that matters
import ScreenCapturer from './lib/capture/ScreenCapturer';

app.on('ready', () => {
// Where I spawn my main UI
mainWindow = new BrowserWindow({...});
mainWindow.loadURL(...);
// Other startup stuff

// Hee comes the part where I call function to start capturing
initCapture();
});

function initCapture() {
const sc = new ScreenCapturer();
sc.startTakingScreenshots();
}

ScreenCapturer.js(主进程使用的模块)

'use strict';

/* ******************************************************************** */
/* IMPORTS */
import { app, BrowserWindow, ipcMain } from 'electron';
import url from 'url';
import path from 'path';
/* VARIABLES */
let rendererWindow;
/*/********************************************************************///
/*///*/

/* ******************************************************************** */
/* SCREENCAPTURER */
export default class ScreenCapturer {
constructor() {
rendererWindow = new BrowserWindow({
show: true, width: 400, height: 600,
'node-integration': true,
webPreferences: {
webSecurity: false
}
});
rendererWindow.on('close', () => {
rendererWindow = null;
});
}

startTakingScreenshots(interval) {
rendererWindow.webContents.on('did-finish-load', () => {
rendererWindow.openDevTools();
rendererWindow.webContents.send('capture-screenshot', path.join('e:', 'temp'));
});
rendererWindow.loadURL(
url.format({
pathname: path.join(__dirname, 'ScreenCapturer.jshtml.html'),
protocol: 'file:',
slashes: true
})
);
}
}
/*/********************************************************************///
/*///*/

ScreenCapturer.jshtml.js(渲染器浏览器窗口中加载的 thml 文件)

<html>
<body>
<script>require('./ScreenCapturer.jshtml.js')</script>
</body>
</html>

ScreenCapturer.jshtml.js(渲染器进程中从html文件加载的js文件)

import { ipcRenderer, desktopCapturer, screen } from 'electron';
import path from 'path';
import fs from 'fs';
import moment from 'moment';
let mainSource;

function getMainSource(mainSource, desktopCapturer, screen, done) {
if(mainSource === undefined) {
const options = {
types: ['screen'],
thumbnailSize: screen.getPrimaryDisplay().workAreaSize
};
desktopCapturer.getSources(options, (err, sources) => {
if (err) return console.log('Cannot capture screen:', err);
const isMainSource = source => source.name === 'Entire screen' || source.name === 'Screen 1';
done(sources.filter(isMainSource)[0]);
});
} else {
done(mainSource);
}
}
function writeScreenshot(png, filePath) {
fs.writeFile(filePath, png, err => {
if (err) { console.log('Cannot write file:', err); }
return;
});
}

ipcRenderer.on('capture-screenshot', (evt, targetPath) => {
setInterval(() => {
getMainSource(mainSource, desktopCapturer, screen, source => {
const png = source.thumbnail.toPng();
const filePath = path.join(targetPath, `${moment().format('yyyyMMdd_HHmmss')}.png`);
writeScreenshot(png, filePath);
});
}, 3000);
});
<小时/>

最佳答案

我不再使用 Electron 提供的 API。我建议使用 desktop-screenshot 包 -> https://www.npmjs.com/package/desktop-screenshot 。这对我来说是跨平台的(linux、mac、win)。注意windows上我们需要hazardous package ,因为否则当使用 asar 打包您的 Electron 应用程序时,它将无法执行 desktop-screenshot 内的脚本。有关危险 package 页面的更多信息。

下面是我的代码现在的大致工作原理,请不要复制/粘贴,因为它可能不适合您的解决方案!不过,它可能会告诉您如何解决该问题。

/* ******************************************************************** */
/* MODULE IMPORTS */
import { remote, nativeImage } from 'electron';
import path from 'path';
import os from 'os';
import { exec } from 'child_process';
import moment from 'moment';
import screenshot from 'desktop-screenshot';
/* */
/*/********************************************************************///
/* ******************************************************************** */
/* CLASS */
export default class ScreenshotTaker {
constructor() {
this.name = "ScreenshotTaker";
}
start(cb) {
const fileName = `cap_${moment().format('YYYYMMDD_HHmmss')}.png`;
const destFolder = global.config.app('capture.screenshots');
const outputPath = path.join(destFolder, fileName);
const platform = os.platform();
if(platform === 'win32') {
this.performWindowsCapture(cb, outputPath);
}
if(platform === 'darwin') {
this.performMacOSCapture(cb, outputPath);
}
if(platform === 'linux') {
this.performLinuxCapture(cb, outputPath);
}
}
performLinuxCapture(cb, outputPath) {
// debian
exec(`import -window root "${outputPath}"`, (error, stdout, stderr) => {
if(error) {
cb(error, null, outputPath);
} else {
cb(null, stdout, outputPath);
}
});
}
performMacOSCapture(cb, outputPath) {
this.performWindowsCapture(cb, outputPath);
}
performWindowsCapture(cb, outputPath) {
require('hazardous');
screenshot(outputPath, (err, complete) => {
if(err) {
cb(err, null, outputPath);
} else {
cb(null, complete, outputPath);
}
});
}
}
/*/********************************************************************///

关于node.js - Electron/NodeJS 和应用程序在 setInterval/async 代码上卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41036935/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com