2014-03-29 95 views
0

所以我一直在困惑這個,只是無法弄清楚如何解決這個問題。Javascript中的範圍/閉包 - 如何更新全局變量?

我有一個嵌套的函數,循環遍歷一個對象數組,並刮擦每個對象的URL的社交鏈接。

之後,我想通過包括{ social: [array of social urls] }來更新每個對象。但是,我得到了{ social: [] }

我試過把contacts[i].social = results放在這個的其他部分,但是我得到一個「找不到對象」的錯誤。

幫助,將不勝感激......

var contacts = [ 
    { title: 'Healthy breakfast: Quick, flexible options to grab at home - Mayo Clinic', 
    url: 'http://www.mayoclinic.org/healthy-living/nutrition-and-healthy-eating/in-depth/food-and-nutrition/art-20048294' }, 
    { title: 'Healthy Breakfast Ideas from Dr. Weil\'s Facebook Readers', 
    url: 'http://www.drweil.com/drw/u/ART03113/Healthy-Breakfast-Ideas-from-Facebook-Readers.html' }, 
    { title: '8 Healthy Breakfast Ideas - Prevention.com', 
    url: 'http://www.prevention.com/food/healthy-eating-tips/8-healthy-breakfast-ideas' }, 
    { title: 'Quick & Easy Healthy Breakfast Ideas! - YouTube', 
    url: 'http://www.youtube.com/watch?v=mD4YSD8LDiQ' }, 
    { title: 'The Best Foods to Eat for Breakfast - Health.com', 
    url: 'http://www.health.com/health/gallery/0,,20676415,00.html' }, 
    { title: 'Healthy Breakfast Recipes - Secrets To Cooking Healthier - YouTube', 
    url: 'http://www.youtube.com/watch?v=7jH0xe1XKxI' }, 
    { title: 'Healthy Breakfast Ideas You Can Make the Night Before - FitSugar', 
    url: 'http://www.fitsugar.com/Healthy-Breakfast-Ideas-You-Can-Make-Night-Before-20048633' }, 
    { title: '10 Easy, 5-Minute Breakfast Ideas - Diet and ... - Everyday Health', 
    url: 'http://www.everydayhealth.com/diet-and-nutrition-pictures/easy-5-minute-breakfast-ideas.aspx' }, 
    { title: 'Healthy Breakfast Ideas for Kids | Parenting - Parenting.com', 
    url: 'http://www.parenting.com/gallery/healthy-breakfast-ideas-kids' }, 
    { title: 'Fruits & Veggies More Matters : Healthy Breakfast Ideas : Health ...', 
    url: 'http://www.fruitsandveggiesmorematters.org/healthy-breakfast-ideas' } 
]; 

scraper(contacts); 

// loops through contacts database and scrapes requested information 
function scraper(contacts) { 

    // Adds the domain of each contact 
    for(var i=0;i<contacts.length;i++){ 
     contacts[i].domain = contacts[i].url.split(/\//, 3).join().replace(/,/g, '/'); 
    }; 

    // 
    for(var i=0;i<contacts.length;i++){ 
     var homepage = contacts[i].domain; 

     var results = []; 

     function socialScrape(homepage) { 
      request(homepage, function(err, resp, html) { 
       var $ = cheerio.load(html); 

       if(!err && resp.statusCode == 200) {  
        $('a').each(function(i, el){ 
         var a = $(el).attr('href'); 
         for(var key in socialURLS){ 
          if(socialURLS[key].test(a) && results.indexOf(a) < 0){ 
           results.push(a); 
          } 
         } 

        }); 
       } else { console.log(err); } 
      }) 
     } 
     contacts[i].social = results; 
     socialScrape(homepage); 
    } 

console.log(contacts); 

} 

回答

1

你的第一個問題是,您的通話request是異步的,還沒有被時間contacts[i].social = results執行返回,所以contacts[i].results是越來越指派一個空數組,[]。 (這個問題的變化每天都在SO上多次發佈,對此問題的一個很好的解釋可以在這裏找到:How do I return the response from an asynchronous call?)解決這個問題並不簡單,只需將contacts[i].social = results;移動到request調用成功處理程序中,因爲值i將在之前更改處理程序被調用。

你的第二個問題是results定義的socialScrape函數定義之外 - 因此不是每request呼叫項目數組,你有一個陣列的所有request結果。爲您解決範圍的問題,最好的辦法是用封閉,我們可以通過刪除調用socialScrape(homepage);,使socialScrape自調用函數實現:

(function socialScrape(homepage) { 
    var results = []; 
    var index = i; 
    request(homepage, function(err, resp, html) { 
     /* do error and status check stuff and build our results array */ 
     contacts[index].social = results; 
    }); 
}(homepage)); 

注意我們是如何捕捉i內的電流值關閉並將其分配給index。這將使我們能夠在交付結果時通過索引獲得正確的聯繫方式。