解决“ DevTools已从页面断开连接”的提示,Electron Helper消失

时间:2019-03-06 21:12:46

标签: debugging electron hang

Electron出现问题,应用程序空白。即它变成白屏。如果我打开开发工具,它将显示以下消息。

enter image description here

在ActivityMonitor中,发生这种情况时,我可以看到Electron Helper进程的数量从3个减少到2个。另外,似乎我不是唯一遇到它的人。例如

但是我还没有找到一个有用的答案。在电子崩溃的情况下,有什么好的方法可以识别问题?

对于上下文,我将sdk加载到Electron中。最初,我是使用browserify对其进行打包的,效果很好。但是我想转到SDK的npm版本。这个版本似乎已经引入了问题(尽管代码应该相同)。

9 个答案:

答案 0 :(得分:3)

我已经安装了谷歌浏览器版本79.0.3945.130(64位)。每当我处于调试模式时,我的应用都会崩溃。我尝试了所有在网络上找到的解决方案,但没有人有用。我降级到所有以前的版本:

  1. 78.x 崩溃
  2. 77.x 崩溃
  3. 75.x 未坠毁

我必须重新安装版本75.0.3770.80(64位)。问题已解决。它可能是Chrome版本的新问题。我已将反馈发送给Chrome浏览器维护。

答案 1 :(得分:1)

自我最初发布此问题以来,已经过去了很多时间。如果我的错误可以帮助任何人,我会自己回答。

我从来没有对原始问题有一个“解决方案”。后来,我转而使用sdk的npm版本,它起作用了。

但是在那之前,我再次遇到了这个问题。幸运的是,到那时,我已经添加了一个记录器,该记录器还向文件写入了控制台。有了它,我注意到JavaScript语法错误导致崩溃。例如缺少右括号等。

我怀疑这就是造成我最初问题的原因。但是,Chrome开发人员工具会清空控制台,而不是在工具崩溃时保留控制台,这是最糟糕的事情。

我用来设置记录器的代码

$mixStdErrIntoStdOut = false;

ob_start();
$exitCode = 0;
if ($mixStdErrIntoStdOut) 
{
    system("pdfgrep -i $keyword $file 2>&1", &$exitCode);
} else {
    system("pdfgrep -i $keyword $file", &$exitCode);
}
$output = ob_get_clean();

var_dump($output);

然后在index.html中,我首先加载此脚本

/*global window */
const winston = require('winston');
const prettyMs = require('pretty-ms');

/**
 * Proxy the standard 'console' object and redirect it toward a logger.
 */
class Logger {
  constructor() {
    // Retain a reference to the original console
    this.originalConsole = window.console;
    this.timers = new Map([]);

    // Configure a logger
    this.logger = winston.createLogger({
      level: 'info',
      format: winston.format.combine(
        winston.format.timestamp(),
        winston.format.printf(({ level, message, timestamp }) => {
          return `${timestamp} ${level}: ${message}`;
        })
      ),
      transports: [
        new winston.transports.File(
          {
            filename: `${require('electron').remote.app.getPath('userData')}/logs/downloader.log`, // Note: require('electron').remote is undefined when I include it in the normal imports
            handleExceptions: true, // Log unhandled exceptions
            maxsize: 1048576, // 10 MB
            maxFiles: 10
          }
        )
      ]
    });

    const _this = this;

    // Switch out the console with a proxied version
    window.console = new Proxy(this.originalConsole, {
      // Override the console functions
      get(target, property) {
        // Leverage the identical logger functions
        if (['debug', 'info', 'warn', 'error'].includes(property)) return (...parameters) => {
          _this.logger[property](parameters);
          // Simple approach to logging to console. Initially considered
          // using a custom logger. But this is much easier to implement.
          // Downside is that the format differs but I can live with that
          _this.originalConsole[property](...parameters);
        }
        // The log function differs in logger so map it to info
        if ('log' === property) return (...parameters) => {
          _this.logger.info(parameters);
          _this.originalConsole.info(...parameters);
        }
        // Re-implement the time and timeEnd functions
        if ('time' === property) return (label) => _this.timers.set(label, window.performance.now());
        if ('timeEnd' === property) return (label) => {
          const now = window.performance.now();
          if (!_this.timers.has(label)) {
            _this.logger.warn(`console.timeEnd('${label}') called without preceding console.time('${label}')! Or console.timeEnd('${label}') has been called more than once.`)
          }
          const timeTaken = prettyMs(now - _this.timers.get(label));
          _this.timers.delete(label);
          const message = `${label} ${timeTaken}`;
          _this.logger.info(message);
          _this.originalConsole.info(message);
        }

        // Any non-overriden functions are passed to console
        return target[property];
      }
    });
  }
}

/**
 * Calling this function switches the window.console for a proxied version.
 * The proxy allows us to redirect the call to a logger.
 */
function switchConsoleToLogger() { new Logger(); } // eslint-disable-line no-unused-vars

答案 2 :(得分:1)

我遇到了这个问题,无法弄清楚DevTool为何不断断开连接。因此,我一时兴起,启动了Firefox Developer版本,并将原因确定为具有字符串长度属性的未定义变量。

if ( args.length > 1 ) {
    $( this ).find( "option" ).each(function () {
        $( $( this ).attr( "s-group" ) ).hide();
    });
    $( args ).show();
}

TL; DR Firefox开发人员版可以在Chrome的DevTool出现故障时识别出此类问题。

答案 3 :(得分:1)

您可以下载Google Chrome Canary。我在Google Chrome上遇到了这个问题,每次DevTools都在同一地点崩溃。在Chrome Canary上,调试器不会崩溃。

答案 4 :(得分:0)

调试此类崩溃的技巧是启用日志记录,默认情况下该日志记录显然处于禁用状态。如ELECTRON_ENABLE_LOGGING=1中所述,这是通过设置环境变量this GitHub issue来完成的。

启用该功能后,您应该在控制台中看到类似的内容:

enter image description here

答案 5 :(得分:0)

阅读上面的评论后,我很清楚至少在 Chrome 中存在一个问题,即没有显示任何故障来源的指示。在 Firefox 中,该程序可以运行,但延迟很长时间。

但是,正如 Shane Gannon 所说,问题的根源当然不在浏览器中,而在代码中:就我而言,我打开了一个while 循环没有添加相应的增量,这使得循环无限。如下例所示:

var a = 0;
while (a < 10) {

  ...

  a ++               // this is the part I was missing;
}

一旦纠正,问题就消失了。

答案 6 :(得分:0)

我发现升级到

  • react 17.0.2
  • react-dom 17.0.2
  • react-scripts 4.0.3

但也因为 react-scripts start 被用于运行电子可能它只是需要更新的反应脚本。

答案 7 :(得分:0)

我的问题是我没有加载诸如 index.html 之类的页面。一旦我加载问题就消失了。

  parentWindow = new BrowserWindow({
    title: 'parent'
  });
  parentWindow.loadURL(`file://${__dirname}/index.html`);
  parentWindow.webContents.openDevTools();

答案 8 :(得分:-1)

打开您的 google 开发控制台 (Ctrl + shift + i)。 然后按 (fn + F1) 或仅按 F1,然后滚动按下并点击恢复默认设置并重新加载。