检查 WebKit 上下文何时在 NW.js 中可用

Posted

技术标签:

【中文标题】检查 WebKit 上下文何时在 NW.js 中可用【英文标题】:Check when WebKit context is available in NW.js 【发布时间】:2016-08-17 10:52:18 【问题描述】:

在 Node 上下文中执行时 (node-main),

setTimeout(function () 
    console.log(nw);
, 20);

抛出

nw 未定义

因为 WebKit 上下文尚未准备好(从一开始window 在 NW.js window.nw 在 NW.js >= 0.13 中不可用)。和

setTimeout(function () 
    console.log(nw);
, 200);

工作正常,但 setTimeout 看起来像个黑客,将其设置为安全延迟值可能会导致不良延迟。

如何从 Node 上下文中检查 WebKit 上下文和 nw 的可用性?有没有合理的方式,比如可以处理的事件?

【问题讨论】:

WebKit 加载选项后是否正在运行你的 node-main 函数? @RahatMahbub 我希望有一种官方(可能未记录)的方式可以仅通过 Node 执行此操作,例如全局事件。这是有道理的,但如果没有,那么我想从 html 页面回调是唯一的选择。 @estus 有一种方法可以做到这一点,但我认为这不是一种特别巧妙的方法。如果您愿意,我可以将其添加到我的答案中。 @Harry 当然,那太好了。答案包含一个很好的介绍性 NW 示例,但没有直接解决问题。 @estus 我向它添加了一个计时器,以便您查看定义 nw 对象需要多长时间。 【参考方案1】:

以下实现了同样的事情,但反过来做。

在您的 html 文件中:

<body onload="process.mainModule.exports.init()">

在你的 node-main JS 文件中:

exports.init = function() console.log(nw);

这里,init 函数仅在 Webkit 上下文/DOM 可用时调用。

【讨论】:

【参考方案2】:

你可以使用pollit :) ...

var pit = require("pollit");
foo = function(data) 
  console.log(nw);
;
pit.nw('nw', foo);    

我已经对其进行了测试,它对我有用:)。这将我在本文接近尾声时给出的解决方案模块化。

nw 对象在 webkit 启动并运行(即浏览器)之前不存在 窗口已创建。这发生在 Node 启动后,这就是为什么你 收到此错误。要使用nw api,您可以创建可以 听或调用全局函数,前者更可取。下面的代码将演示两者,并且应该让您很好地了解 NodeWebKit 是如何相互连接的。

此示例创建一个窗口,打开开发工具并允许您切换 屏幕。它还在控制台中显示鼠标位置。它还演示了如何使用 DOM 发送事件,即 body.onclick() 并从 Node 中附加事件,即我们将捕获 minimize 事件并将它们写入控制台。

为此,您需要使用 SDK 版本的 NW。这是我的 package.json


  "name": "hello",
  "node-main": "index.js",
  "main": "index.html",
  "window": 
    "toolbar": true,
    "width": 800,
    "height": 600
  ,
  "dependencies" : 
    "robotjs" : "*",
    "markdown" : "*"
  

你需要的两个文件是index.html

<!DOCTYPE html>
<html>
  <head>
    <script>
      var win = nw.Window.get();
      global.win = win;
      global.console = console;
      global.main(nw);
      global.mouse();
      var markdown = require('markdown').markdown;
      document.write(markdown.toHTML("-->Click between the arrows to toggle full screen<---"));
    </script>
  </head>
  <body onclick="global.mouse();">
  </body>
</html>

index.js

var robot = require("robotjs");

global.mouse = function() 
  var mouse = robot.getMousePos();
  console.log("Mouse is at x:" + mouse.x + " y:" + mouse.y);
  global.win.toggleFullscreen();


global.main = function(nw_passed_in) 
  global.win.showDevTools();
  console.log("Starting main");
  console.log(nw_passed_in);
  console.log(nw);
  global.win.on('minimize', function() 
    console.log('n: Window is minimized from Node');
  );

运行时我使用了

nwjs --enable-logging --remote-debugging-port=1729  ./

然后您可以使用

打开浏览器
http://localhost:1729/

如果需要,用于调试。

如果您想在nw 对象存在后立即执行某项操作,您可以轮询它。我会使用 eventEmitter,如果你不想使用事件发射器,你可以很容易地将它包装在一个函数中并递归调用它。下面将显示在设置 nw 对象之前花费了多少毫秒。在我的系统上,这介于 43 - 48 毫秒之间。使用递归函数也不例外。如果您将其添加到上面的代码中,您将看到所有内容都记录到控制台。

var start = new Date().getTime();
var events = require('events');
var e = new events.EventEmitter();

var stop = 0;
e.on('foo', function()  
if(typeof nw === 'undefined') 
  setTimeout(function () 
    e.emit('is_nw_defined');
  , 1); 
    
 else 
   if(stop === 0) 
     stop = new Date().getTime();
      
   setTimeout(function () 
     console.log(stop - start);
     console.log(nw);
     e.emit('is_nw_defined');
   , 2000);
    
);
e.emit('is_nw_defined');

【讨论】:

感谢 pollit 软件包,看起来像一个 hack 但很好,性能损失和过度延迟几乎为零。【参考方案3】:

解决方案 1:

您可以使用onload、see reference。

ma​​in.js:

var gui = require("nw.gui"),
    win = gui.Window.get();

onload = function() 
    console.log("loaded");
    console.log(win.nw);
;

index.html:

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript" src="main.js"></script>
    </head>
    <body></body>
</html>

package.json:


  "name": "Freebox",
  "main": "index.html"

解决方案 2:

(为了防止问题,但不是必须的)。

var gui = require("nw.gui"),
    win = gui.Window.get();

onload = function() 
    console.log("loaded");
    var a = function () 
        if (!win.nw) return setTimeout(a, 10);
        console.log(win.nw);
    ;
;

【讨论】:

这个解决方案是错误的。 require('nw.gui') 是获取 nw 对象的传统方式。您也错过了 OP 关于上下文的观点,您在此答案的任何时候都不在节点上下文中。 @Harry 这是一个例子。【参考方案4】:

我最初提出的解决方案看起来像

app-node.js

process.once('webkit', () => 
    console.log(nw);
);

app.html

<html>
<head>
    <script>
        global.process.emit('webkit');
    </script>
    ...

我很高兴知道已经有一个事件要监听,因此跨平台客户端脚本可以省略与 NW 相关的代码。

【讨论】:

以上是关于检查 WebKit 上下文何时在 NW.js 中可用的主要内容,如果未能解决你的问题,请参考以下文章

node webkit (nw.js) 无法调试的结局方案之一

nw.js node-webkit基本程序结构与配置package.json配置说明

Node-Webkit打包

Node-Webkit打包

nw.js使用

节点 webkit 热键示例不起作用