1

Тема: WSH: Не запускается обработчик события DocumentComplete

Доброго времени суток!

Имеется следующая проблема: после попытки спрятать создание экземпляра ie в функцию-конструктор перестала выполняться функция, которая вызывалась после загрузки страницы (событие DownloadComplete).
Сперва было вот так (этот пример рабочий):

<?xml version="1.0" encoding="UTF-8" ?>
<job id="T1">
  <script language="JScript"><![CDATA[

    var forever = true;

    function f(doc) {
      doc.title = "Теst";
    }

    function ie_OnQuit() {
      forever = false;
    }
    
    function ie_DocumentComplete() {
      doc = ie.Document;

      if (typeof f == 'function') f(doc);

      ie.Visible = true;
    }

    var ie = WScript.CreateObject("InternetExplorer.Application", "ie_");

    while (ie.Busy) {
      WScript.Sleep(200);
    }

    ie.Navigate("about:blank");

    while (forever) {
      WScript.Sleep(200);
    }

  ]]></script>
</job>

А после того, как создание объекта было спрятано в функцию:

<?xml version="1.0" encoding="UTF-8" ?>
<job id="T1">
  <script language="JScript"><![CDATA[

  var form = new MakeIE();
  form.setAfterCompleteFunc(f);
  form.load(200, "about:blank");

  function f(doc) {
    doc.title = "test";
  }

  function MakeIE(func) {
    var forever = true;
    var f = func;
    var ie = WScript.CreateObject("InternetExplorer.Application", "ie_");

    function ie_OnQuit() {
      forever = false;
    }
    
    function ie_DocumentComplete() {
      doc = ie.Document;
      doc.focus();
      window = doc.parentWindow;

      if (typeof f == 'function') f(doc);

      ie.Visible = true;
    }

    this.load = function(pause, url) {

      while (ie.Busy) {
        WScript.Sleep(pause);
      }

      ie.Navigate("about:blank");

      while (forever) {
        WScript.Sleep(pause);
      }
    };

    this.setAfterCompleteFunc = function(func) {
      f = func;
    };
  }
  
  ]]></script>
</job>

функция "ie_DocumentComplete" перестала выполняться... можно, конечно обойтись проверкой в цикле значения ReadyState для принудительного выполнения этой функции, но хотелось бы сперва понять, почему второй пример не работает...

2

Re: WSH: Не запускается обработчик события DocumentComplete

Функция ie_DocumentComplete - локальная, существующая только внутри функции MakeIE. По завершении работы MakeIE все локальные сущности уничтожаются.

( 2 * b ) || ! ( 2 * b )

3

Re: WSH: Не запускается обработчик события DocumentComplete

Нет, и это легко проверить, достаточно изменить метод load на такой:

    this.load = function(pause, url) {

      while (ie.Busy) {
        WScript.Sleep(pause);
      }

      ie.Navigate("about:blank");

      while (ie.ReadyState < 4) {
        WScript.Sleep(pause);
      }
      
      ie_DocumentComplete();

      while (forever) {
        WScript.Sleep(pause);
      }
    };

И функция отработает, хотя конструктор уже давно завершился: локальные переменные и функции остались в замыкании...

Хорошо, а как бы Вы решили данную задачу?

4

Re: WSH: Не запускается обработчик события DocumentComplete

Ратибор Редоран
1) Rumata прав. Дело именно в том, что обработчик событий WScript смотрит только на функции верхнего уровня.

Хорошо, а как бы Вы решили данную задачу?

а) Попытался бы отказаться от использования IE вовсе. Грузный тяжеловесный объект. К тому же не всегда работает адекватно.
б) Попробовал бы использовать WinHttp.WinHttpRequest.5.1 / Msxml2.XMLHTTP.6.0 и подобные  в связке с объектом htmlfile
в) В случае крайней необходимости именно IE, собрал бы Windows Script Component c обработчиками событий, как в первом примере, а в основном скрипте получал бы экземпляры объекта
г) Посмотрел бы в сторону HTA. Подгрузку данным там можно сделать нативными средствами.

Всё зависит от конкретной цели. Не зная её, сложно судить о конечной реализации. Путей решения много, правильных и оптимизированных меньше.

2)

И функция отработает, хотя конструктор уже давно завершился: локальные переменные и функции остались в замыкании...
Хорошо, а как бы Вы решили данную задачу?

Хм. А из чего видно, что конструктор завершился ? Возможно Вас не понял, но вы вызываете функцию ie_DocumentComplete принудительно между циклами. Она спокойно отрабатывает и скрипт завершается. Разве не так ?

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

5 (изменено: wisgest, 2016-02-02 08:27:34)

Re: WSH: Не запускается обработчик события DocumentComplete

Ратибор Редоран пишет:

Хорошо, а как бы Вы решили данную задачу?

Насколько я понимаю и помню, можно:
объявить ie_DocumentComplete как глобальную переменную или как свойство глобального объекта (второе можно сделать и внутри функции MakeIE)
и уже в функции присвоить ей ссылку на нужную локальную функцию.

6

Re: WSH: Не запускается обработчик события DocumentComplete

wisgest, да. Действительно, один из вариантов.


var ie = WScript.CreateObject('InternetExplorer.Application','ie_')

ie.Visible = true

navigate('http://www.yandex.ru');

function navigate(url){
	this.ie_DocumentComplete = function(){
		WScript.Echo('document complete');
	}
	ie.navigate(url);
	while(ie.Busy){
		WScript.Sleep(100);
	}
}
Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

7

Re: WSH: Не запускается обработчик события DocumentComplete

Xameleon

Хм. А из чего видно, что конструктор завершился ? Возможно Вас не понял, но вы вызываете функцию ie_DocumentComplete принудительно между циклами. Она спокойно отрабатывает и скрипт завершается. Разве не так ?

Верно, только ie_DocumentComplete вызывается в методе load, который выполняется уже после того как отработает конструктор (и вернет this).

5wisgest

объявить ie_DocumentComplete ... как свойство глобального объекта (... можно сделать и внутри функции MakeIE)
и уже в функции присвоить ей ссылку на нужную локальную функцию.

Попробовал - получилось. Вариант вполне рабочий, спасибо Вам!

Xameleon

Дело именно в том, что обработчик событий WScript смотрит только на функции верхнего уровня.

А вот этого я не знал... Теперь понятно, почему функция не отрабатывала.

8

Re: WSH: Не запускается обработчик события DocumentComplete

Ратибор Редоран,

Верно, только ie_DocumentComplete вызывается в методе load, который выполняется уже после того как отработает конструктор (и вернет this).

Кажется понял, что Вы имеете в виду. Действительно конструктор уже отработал, но функции доступны, потому что строкой

var form = new MakeIE();

был создан объект, ссылка на который держится в переменной form. И пока она существует, функции внутри будут доступны. В данном случае он (объект) будет уничтожен по концу работы скрипта. Думаю Rumata говорил не о моменте завершения работы конструктора, а о моменте уничтожения объекта в переменной и её самой. Если ошибаюсь, надеюсь он меня поправит. Но проблема была именно в том, что функция была запрятана внутрь MakeIE, поэтому обработчик событий WScript её не видел.

P.S Истина где-то рядом )

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !