Проверьте, доступен ли контекст WebKit в NW.js

Выполняется в контексте Node (node-main),

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

бросает

nw не определен

потому что контекст WebKit не готов (с самого начала window недоступен в NW.js <= 0.12, window.nw в NW.js >= 0.13). И

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

работает просто отлично, но setTimeout выглядит как взломать, устанавливая его в безопасное значение задержки, может вызвать нежелательное отставание.

Как можно проверить наличие контекста WebKit и nw из контекста Node? Есть ли разумный способ, как событие, которое можно было бы обработать?

Ответ 1

Решение, которое я изначально придумал, выглядит как

app- node.js

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

app.html

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

Я был бы рад узнать, что уже есть событие для прослушивания, поэтому межплатформенные клиентские скрипты могут пропустить код, связанный с NW.

Ответ 2

Следующее выполняет одно и то же, но делает это наоборот.

В вашем html файле:

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

В вашем node -ном JS файле:

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

Здесь функция init вызывается только при наличии контекста WebKit/DOM.

Ответ 3

Вы можете использовать pollit:)...

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

Я тестировал его, и он работает для меня:). Это модулирует решение, которое я даю ближе к концу этого.

Объект nw не существует, пока webkit не запущен и не запущен, т.е. браузер окно было создано. Это происходит после запуска Node, поэтому вы получив эту ошибку. Чтобы использовать nw api, вы создаете события, которые могут быть слушали или называли глобальные функции, которые предпочтительнее. Следующий код продемонстрирует оба и должен дать вам представление о том, как Node и WebKit взаимодействуют друг с другом.

В этом примере создается окно, открывается devtools и позволяет переключать экран. Он также отображает местоположение мыши в консоли. Он также демонстрирует, как отправлять события с помощью DOM, т.е. body.onclick() и присоединять события из Node, то есть мы собираемся поймать события minimize и записать их на консоль.

Для этого вам нужно использовать версию SDK nw. Это мой пакет .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, если вы не хотите использовать event emitter, вы можете просто просто обернуть это в функцию и вызвать его рекурсивно. Ниже будет показано, сколько миллисекунд было выполнено до того, как объект 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');

Ответ 4

Решение 1:

Вы можете использовать onload, см. ссылку.

main.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);
    };
};