2015-12-18 3 views
3

Я недавно создавал модуль скребка, чтобы получить некоторую информацию с nodejs, пока не столкнулся с этой «маленькой» проблемой. Модули, которые я использую, являются cheeriojs и требуют. На самом деле модуль работает как шарм, если я вызываю только один метод за раз. Он содержит три функции, и только два из них экспортируются, это код:Функции, которые не могут выполняться вместе

'use strict'; 

var request = require('request'), 
    cheerio = require('cheerio'), 
    counter = 0; 

function find(term, cat, callback) { 
    // All the check for the parameters 
    scrape("http://.../search.php?search=" + encodeURIComponent(term), cat, callback); 
} 

function last(cat, callback) { 
    // All the check for the parameters 
    scrape("http://google.com/", cat, callback); 
} 

function scrape(url, cat, callback) { 
    request(url, function (error, response, body) { 
    if (!error && response.statusCode == 200) { 
     var $ = cheerio.load(body); 
     var result = []; 

     var items = $('.foo, .foo2').filter(function() { 
     // Condition to filter the resulted items 
     }); 

     items.each(function(i, row) { 
     // Had to do another request inside here to scrape other information 
     request($(".newpagelink").attr("href"), function(error, response, body) { 
      var name = $(".selector").text(), 
       surname = $(".selector2").text(), 
       link = cheerio.load(body)('.magnet').attr('href'); // This is the only thing that I'm scraping from the new page, the rest comes from the other "cheerio.load" 
     // Push an object in the array 
     result.push({ "name": name, "surname": surname, "link": link }); 

      // To check when the async requests are ended 
      counter++; 
      if(counter == items.length-1) { 
      callback(null, result); 
      } 
     }); 
     }); 
    } 
    }); 
} 

exports.find = find; 
exports.last = last; 

Проблема теперь, как я уже говорил, что если я создаю новый сценарий узла «test.js» и я называю только последний ИЛИ найти, он отлично работает! Но если я позвоню как методы последовательно, как это:

var mod = require("../index-tmp.js"); 
mod.find("bla", "blabla", function(err, data) { 
    if (err) throw err; 
    console.log(data.length + " find"); 
}); 
mod.last(function(err, data) { 
    console.log(data.length + " last"); 
}); 

Результаты полностью перепутались, иногда сценарий даже не напечатать что-то, в другое время печати результат только «найти» или «последний», и другие времена возвращают ошибку cheeriojs (я не буду добавлять сюда, чтобы не повредить вам, потому что, вероятно, это ошибка моего сценария). Я думал также повторить одну и ту же функцию два раза для обоих методов, но ничего, те же проблемы возникают ... Я не знаю, что еще попробовать, надеюсь, вы скажете мне причину такого поведения!

+0

Btw, 'counter == items.length-1' выглядит подозрительно. Почему бы не дождаться всех предметов? Также вам не хватает обработки ошибок во внутреннем обратном вызове 'request', и' callback' никогда не будет вызываться, если 'items.length == 0' – Bergi

+0

@Bergi items.length-1, потому что последний является пустым полем, который Мне не нужно царапать. Обработка ошибок, как вы можете видеть также из других функций, не включена в этот пост, чтобы не сделать это слишком долго, я просто забыл удалить и первый. В любом случае, это работает, вставив счетчик внутрь ... Я потратил 2 часа на мою жизнь на эту проблему. Большое спасибо –

+2

Из кода, который вы нам показали, вы по-прежнему отправляете «запрос» для последнего окна ... И обратите внимание, что вы не можете быть уверены, кто из них игнорируется, потому что он прибывает последним. – Bergi

ответ

3

Ваша counter переменная глобальна, не относится к каждому вызову scrape. Это не сработает, если вы одновременно назовете find или last.

Переместить объявление и инициализацию var counter = 0; в функцию scrape, или даже лучше, прямо рядом с result и items деклараций.

0

Из-за быстрого сканирования кода это, вероятно, связано с тем, что переменная counter является глобальной. Это асинхронные функции, поэтому они будут действовать на counter на том же самом. Переместите декларацию внутри функции scrape.

Если вам нужна дополнительная информация об асинхронном программировании, обратитесь к отличному ответу Феликса в this question.

Смежные вопросы