2016-11-23 35 views
0

我看了一些关于这个主题的其他问题,但是在这种情况下无法包装我的头如何实现它。Nodejs:比较两个异步请求的结果

我想实现:

  1. 访问网站,并获得内容(身体)
  2. 访问相匹配的测试网站,并获得内容(身体)
  3. 比较内容的第1页
  4. 抓取链接
  5. 第2页的抓取链接
  6. 继续

我目前遇到的问题是我无法比较内容,因为请求并未等待对方。 这是我的代码现在的样子。

require('colors'); 
var request = require('request'); 
var cheerio = require('cheerio'); 
var jsdiff = require('diff'); 
var URL = require('url-parse'); 

var PROD_START_URL = "https://www.somesite.org"; 
var MAX_PAGES_TO_VISIT = 100; 

var pagesVisited = {}; 
var numPagesVisited = 0; 
var pagesToVisit = []; 

var globalProdContent; 
var globalTestContent; 

var url = new URL(PROD_START_URL); 
var baseUrl = url.protocol + "//" + url.hostname; 

pagesToVisit.push(PROD_START_URL); 
crawl(); 

function crawl() { 
    if(numPagesVisited >= MAX_PAGES_TO_VISIT) { 
    console.log("Reached max limit of number of pages to visit."); 
    return; 
    } 
    var nextPage = pagesToVisit.pop(); 
    if (nextPage in pagesVisited) { 
    // We've already visited this page, so repeat the crawl 
    crawl(); 
    } else { 
    // New page we haven't visited 
    visitPage(nextPage, crawl); 
    } 
} 

function visitPage(url, callback) { 
    // Add page to our set 
    pagesVisited[url] = true; 
    numPagesVisited++; 

    // Make the request 
    console.log("Visiting page " + url); 
    request(url, function(error, response, body) { 
    // Check status code (200 is HTTP OK) 
    console.log("Status code: " + response.statusCode); 
    if(response.statusCode !== 200) { 
     callback(); 
     return; 
    } 
    // Parse the document body 
    var $ = cheerio.load(body); 
    globalProdContent = $("#wrapper").text(); 

    // Build new URL for test site 
    var testURL = url.replace("https://www.somesite.org", "http://matching.testsite"); 

    // Scrape test site 
    scrapeTestContent(testURL); 


    collectInternalLinks($); 
    callback(); 
    }); 
} 

function collectInternalLinks($) { 
    var relativeLinks = []; 
    relativeLinks = $("a[href]"); 

    console.log("Found " + relativeLinks.length + " relative links on page"); 
    relativeLinks.each(function() { 
     pagesToVisit.push(baseUrl + "/" + $(this).attr('href')); 
    }); 
} 

function scrapeTestContent(testURL) { 
    console.log("Visiting matching testpage " + testURL); 
    request(testURL, function(error, response, body) { 
     console.log("Status code: " + response.statusCode); 
     if(response.statusCode !== 200) { 
      callback(); 
     return; 
     } 

     var $ = cheerio.load(body); 
     globalTestContent = $("#wrapper").text(); 
     console.log(globalTestContent); 

    }); 
} 

有没有更简单的方法来做到这一点,还是我完全脱离轨道?

回答

0

这可以通过两种方式来完成: 1.添加回调scrapeTestContent

function scrapeTestContent(testURL, cb) { 
     ... 
     request(testURL, function(error, response, body) { 
      cb(); 
     }); 

    In visitPage, 

    function visitPage(url, callback) { 
     ... 
     scrapeTestContent(testURL,() => collectInternalLinks($)); 
    } 
  • 使用ES6承诺。在scrapeTestContent()返回new Promise((resolve, reject) => {}。然后在visitPage,使用以下构造:scrapeTestContent(testUrl).then(() => collectInternalLinks($))