Задать вопрос
@cat_crash

NodeJS + jsDom синхронный вызов?

Снова я вокруг и около своей проблемы. Никак не могу ее решить.

Собственно сама задача проста но из за асинхронно-синхронности ноды топчусь по граблям и не могу решить ее.



Задача сводится к простым вещам — есть массив с URLами. В цикле при помощи jsdom+jquery разбираем страницу, выбираем все URLы и запихиваем их в конец массива для дальнейшей обработки внутри цикла.



Есть какие либо идеи как реализовать?



var jsdom = require("jsdom");<br>
var fs = require("fs");<br>
var jquery = fs.readFileSync("./jquery.js").toString();<br>
<br>
var fields = ['http://some.url/page.html']<br>
<br>
for(var b=0, len = fields.length;b<len;b++){<br>
<br>
jsdom.env({<br>
      html: fields[b],<br>
      src: [jquery],<br>
      done: function (errors, window) {<br>
            var $ = window.$;<br>
            $("div.pager a").each(function() {<br>
                //Push new finded hyperlinks in array<br>
              fields.push($(this).attr('href'));<br>
            });<br>
<br>
        }<br>
    });<br>
    //recalculate actual length of array to make more loop<br>
    len=fields.length;<br>
}<br>




Кросс пост на StackOverflow
  • Вопрос задан
  • 5757 просмотров
Подписаться 2 Оценить Комментировать
Решения вопроса 1
Mithgol
@Mithgol
var jsdom = require('jsdom');
var fs = require('fs');
var jQuery = fs.readFileSync('jquery.js', 'utf8');
var fields = ['http://some.url/page.html']

var processNextField = function(nextField){
   jsdom.env({
      html: nextField,
      src: [jQuery],
      done: function (errors, window) {
         var $ = window.$;
         $("div.pager a").each(function() {
            //Push new finded hyperlinks in array
            fields.push($(this).attr('href'));
         });
         if (fields.length > 0) {
            process.nextTick(function(){
               processNextField( fields.pop() );
            });
         }
      }
   });
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 4
pomeo
@pomeo
иногда парсю сайты на node.js и пользуюсь этой штукой node.io
делаю в два захода, в первом заходе собираю урлы в файлы, вторым заходом через input/output скармливаю файл с урлами и на выходе получаю что мне надо.
В отличие от jsdom, который при долгой работе просто адово течёт и сделать с этим ничего нельзя, node.io работает без проблем. В wiki много понятных примеров.
Если вам не нужны конструкции «div > a», парсер node.io работает только с CSS1 селекторами, хотя jsdom тоже можно подключить.
Ответ написан
Комментировать
@mayorovp
Внутри done нужно проверить, закончена ли работа, и вызвать callback…

var waiting = fields.length;
for(var b=0, len = fields.length;b<len;b++){
  jsdom.env({
      html: fields[b],
      src: [jquery],
      done: function (errors, window) {
            var $ = window.$;
            $("div.pager a").each(function() {
                //Push new finded hyperlinks in array
              fields.push($(this).attr('href'));
            });
            if (--waiting == 0)
              callback(fields);
        }
    });
}


Здесь callback — это функция, которая выполнится после парсинга всех входных файлов.
Ответ написан
@mayorovp
Так, извиняюсь за прошлый ответ — я не понял, что требуется именно рекурсивный обход.

К сожалению, я не знаю node.js и jsdom, чтобы расписать все подробнее.
Ответ написан
Комментировать
@aretmy
Конечно, не совсем уверен, точнее, совсем не уверен, но может это натолкнет вас на решение.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы