@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
  • Вопрос задан
  • 5752 просмотра
Решения вопроса 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
Конечно, не совсем уверен, точнее, совсем не уверен, но может это натолкнет вас на решение.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы