2015-01-06 2 views
2

При построении довольно сложного скребка я наткнулся на проблему с потоком управления моего кода.Узел async.series problem

Что происходит в коде ниже: 1) запрос URL 2) скоблить NEWURL из результатов 3) передать его читаемости API в первой функции асинхронной 4) здесь приходит беда - я никогда не получить следующий асинхронная функция, которая сохраняет читаемость данных для DB

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

request(URL, function(error, response, html) { 
    if (!error) { 
     var $ = cheerio.load(html); 
      NEWURL = data.find('a').attr('href'); 

      readabilityData = {}     
      var articleUrl = 'https://readability.com/api/content/v1/parser?url=' + NEWURL + token; 

      async.series([ 
       function(){ 
        request(articleUrl, function(error, response, html) { 
         if (!error) { 
          readabilityData = response.toJSON(); 
         } 
        }); 
       }, 
       function(readabilityData){ 
        Article.findOne({ 
         "link": url // here's the 
        }, function(err, link){ 
         if(link) { 
          console.log(link) 
         } else { 
           var newArticle = new Article({ 
         // write stuff to DB 
           }); 
           newArticle.save(function (err, data) { 
         // save it 
           }); 
         } 
        }); 
       } 
      ], 
      function(err){ 
       console.log('all good — data written') 
      }); 


     }); 
    } 
}); 
+0

ты говоришь, что функция, в которой вы написали Article.findOne .... никогда не вызывается? – Sikorski

+0

Да, точно. Извините за плохое описание. – walkthroughthecode

ответ

1

Вы должны вызвать параметр обратного вызова, который передается в функцию async.series вызова, когда работа каждой функции является полной. Вот как async.series знает, что он может перейти к следующей функции. И не переопределяйте readabilityData в качестве параметра функции, когда вы пытаетесь использовать его для обмена данными по всем функциям.

Так что-то вроде:

var readabilityData = {}; 

async.series([ 
    function(callback){ 
     request(articleUrl, function(error, response, html) { 
      if (!error) { 
       readabilityData = response.toJSON(); 
      } 
      callback(error); 
     }); 
    }, 
    function(callback){ 
     Article.findOne({ 
      "link": url // here's the 
     }, function(err, link){ 
      if(link) { 
       console.log(link); 
       callback(); 
      } else { 
        var newArticle = new Article({ 
      // write stuff to DB 
        }); 
        newArticle.save(function (err, data) { 
      // save it 
         callback(err); 
        }); 
      } 
     }); 
    } 
], 
function(err){ 
    console.log('all good — data written') 
}); 
+0

Это помогло, спасибо! однако все вещи из readabilityData «не определены», когда я сохраняю его в DB. Я пропущу что-то очевидное? – walkthroughthecode

+1

@JohnnyHK, я бы предложил отредактировать, функции async.series фактически принимают два параметра: один обратный вызов, а другой - результат предыдущей функции. Это фактически сделает OP также осведомленным о том, как использовать результаты предыдущих функций. – Sikorski

+1

@Sikorski Вы думаете о 'async.waterfall',' async.series' не поддерживает это. 'readabilityData' должен быть объявлен как' var readabilityData = {}; 'так, чтобы он не был глобальным, но отличным от этого он прекрасен. – JohnnyHK