2013-06-05 17 views
5

Düğüm, ifade, moğol ve süreç içinde javascript öğreniyorum. Rssparser kullanarak, hikaye listesi almak ve mongoose ile bir mongo veritabanına kaydetmek bir özellik elde etmeye çalışıyorum.Dizide yineleme ve firavuna kaydetme konusunda sorun yaşıyorum. Geri arama sorunu mu var?

Ben RSS çekme çalışma var ve ben hikayeleri yineleme ediyorum, ben sorunlar yaşıyorum kurtarılmaya. 1) 1) hikayenin veritabanında olmadığını ve 2) eğer kaydetmediğini kontrol etmek istiyorum. Geri aramaların ele alındığı yollarda kaybolduğumu düşünüyorum. İşte şimdiki kodum, yorumlarla. Bu çalıştığında

rssparser.parseURL(url, options, function(err,out){ 
    // out.items is an array of the items pulled 
    var items = out.items; 
    var story; 
    for (var i=0; i<items.length; i++){ 

     //create a mongoose story 
     story = new schemas.Stories({ 
      title: items[i].title, 
      url: items[i].url, 
      summary: items[i].summary, 
      published: items[i].published_at 
     }); 

     //TODO: for testing - these show up correctly. 
     //If I pull 10 stories, I get 10 entries from here that match 
     //So "story" is holding the current story 
     console.log("items[i] is :" + items[i].title); 
     console.log("story title is : " + story.title); 

     // setup query to see if it's already in db 
     var query = schemas.Stories.findOne({ 
      "title" : story.title, 
      "url" : story.url 
     }); 


     //execute the query 
     query.exec(function(err, row){ 
      if(err) console.log("error-query: " + err); 
      console.log("row: "+ row); 
      if(!row) { 
       // not there, so save 
       console.log('about to save story.title: ' + story.title); 
       story.save(function (err){ 
        console.log("error in save: " + err); 
       }); 
      } 
     }); 

    } 
}); 

, benim gördüğüm konsol çıkış sürü geçerli:

Tüm hikayeleri (birçok atlanmış) gösterilmeye başladığında oluyor:

items[i] is :TSA Drops Plan to Let Passengers Carry Small Knives on Planes    
story title is : TSA Drops Plan to Let Passengers Carry Small Knives on Planes   
items[i] is :BUILDING COLLAPSE:1 Reportedly Dead, 13 Pulled From Philly Rubble   
story title is : BUILDING COLLAPSE:1 Reportedly Dead, 13 Pulled From Philly Rubble  
items[i] is :CONTROVERSIAL PAST: Obama's UN Nominee Once Likened US 'Sins' to Nazis'  
story title is : CONTROVERSIAL PAST: Obama's UN Nominee Once Likened US 'Sins' to Nazis' 
items[i] is :WRITING OUT WRIGHTS: Bill Gives First Powered Flight Nod to Whitehead  
story title is : WRITING OUT WRIGHTS: Bill Gives First Powered Flight Nod to Whitehead 
items[i] is :BREAKING NEWS: Rice Named to Top Security Post Despite Libya Fallout   
story title is : BREAKING NEWS: Rice Named to Top Security Post Despite Libya Fallout 

Sonra böyle devam (birçok atlanmış):

row: null                  
about to save story.title: Best Ribs in America        
row: null                  
about to save story.title: Best Ribs in America        
row: null                  
about to save story.title: Best Ribs in America        
row: null                  
about to save story.title: Best Ribs in America        
row: null                  
about to save story.title: Best Ribs in America        
row: null                  
about to save story.title: Best Ribs in America        
row: { title: 'Best Ribs in America',           
    url: 'http://www.foxnews.com/leisure/2013/06/05/10-best-ribs-in-america/', 
    published: 1370463800000,             
    _id: 51af9f881995d40425000023,            
    __v: 0 }                  

o (yemlerde son hikaye) "kurtarmak üzere" başlığını tekrarlar ve kaydeder Bir kez, son sıradaki gibi.

console.log çıkış gösterileri

sadece Dibinde query.exec() çağrısı içinden, sonra üstündeki tüm eşyalarını bütün hikaye başlık çıkışını koydu. Herhangi bir yardım takdir

...

cevap

1

bu sorun exec geri arama başvurulan hikaye son şey döngü üzerinde iterated ne olursa olsun ayarlı edilmiş olmasıdır kez geri arama alacak yürütüldü, çünkü yürütülen tüm işlevler değişkenin aynı örneğine başvuruyor.

bu basitçe nda olduğu gibi hemen parametrelerle yürütmek bir işlevde döngü her şeyi sarmak için olduğunu gidermenin en kolay yolu: Bu test değil

rssparser.parseURL(url, options, function(err,out){ 
    // out.items is an array of the items pulled 
    var items = out.items; 
    for (var i=0; i<items.length; i++){ 
     (function(item) { 

      //create a mongoose story 
      var story = new schemas.Stories({ 
       title: item.title, 
       url: item.url, 
       summary: item.summary, 
       published: item.published_at 
      }); 

      // setup query to see if it's already in db 
      var query = schemas.Stories.findOne({ 
       "title" : story.title, 
       "url" : story.url 
      }); 

      //execute the query 
      query.exec(function(err, row){ 
       if(err) console.log("error-query: " + err); 
       console.log("row: "+ row); 
       if(!row) { 
        // not there, so save 
        console.log('about to save story.title: ' + story.title); 
        story.save(function (err){ 
         console.log("error in save: " + err); 
        }); 
       } 
      }); 

     })(items[i]); 
    } 
}); 

ama Sorununuzu düzeltebileceğini bulacağınızdan emin olabilirsiniz

Platformunuz bunu destekliyorsa (ör. node.js) bir başka forte daha kolay, daha temiz, daha iyi bir yol, bir forEach döngüsündeki öğeler üzerinde yineleme yapmaktır.) yapar - bu sürüm daha güzel olduğunu:

rssparser.parseURL(url, options, function(err,out){ 
    // out.items is an array of the items pulled 
    out.items.forEach(function(item) { 

     //create a mongoose story 
     var story = new schemas.Stories({ 
      title: item.title, 
      url: item.url, 
      summary: item.summary, 
      published: item.published_at 
     }); 

     // setup query to see if it's already in db 
     var query = schemas.Stories.findOne({ 
      "title" : story.title, 
      "url" : story.url 
     }); 

     //execute the query 
     query.exec(function(err, row){ 
      if(err) console.log("error-query: " + err); 
      console.log("row: "+ row); 
      if(!row) { 
       // not there, so save 
       console.log('about to save story.title: ' + story.title); 
       story.save(function (err){ 
        console.log("error in save: " + err); 
       }); 
      } 
     }); 

    }); 
}); 
+0

Temizleyici yöntemi uyguladık ve harika çalıştı, teşekkürler. Benim problemim sadece bir zamanlama meselesi miydi? diğer bir deyişle, out.items'deki tüm öğeler, bu geri çağırma gerçekleşmeden önce yinelenmiştir (böylece hikaye son çıkışa ayarlanmıştır)? – Mike

+0

Sorununuz, bir yarış durumuyla sonuçlanan scoping ile ilgisi vardı. for döngüsü yinelendiğinde, "hikaye" ye yalnızca bir referans vardır ve dizi üzerinde yinelediğiniz her zaman geçersiz kılınır. Exec işlevi hemen yürütülürse, eşzamanlı olarak kodunuz iyi çalışırdı, ancak for döngüsü tamamlandıktan sonra yürütmedeki geri çağrıya yapılan tüm çağrılar gerçekleştiği için, tümü değişkene atanan öykünün son örneğine başvururlar. Öykü. Bir işlevle "kapalı" olduklarında, hepsinin kendi hikayesi vardır. Bu çok yaygın bir hata – arnorhs

2

kuyu, düğüm olay tabanlı sunucu ve javascript de olay yürütülür, bu nedenle eşzamansız olarak bir şeyler arayabilirsiniz.

istediğini yapmak için bazı zaman uyumsuz desen kullanmak gerekir. Eğer mongoose kullanıyorsanız

ilk, bunu zaten yeniden db sorgulama olmadan var öğeleri kontrol etmek için şema sınıfı var yararlanabilirler:

var mongoose = require('mongoose'); 

var schema = new mongoose.Schema({ 
    title: String, 
    url: { type: String, unique: true }, 
    summary: String, 
    published: Date 

}) 

var model = mongoose.model('stories', schema) 

url tektir, bu nedenle bir yinelenen neden olacaktır kurtarmak hata ve firavun sorguyu kaydetmez.

şimdi bunun için bir model çeşit ihtiyaç her biri öğeler arasında yineleme ve kaydetmek için, neyse ki biz bunun için async var: biz değiliz biz paralel modda asenk kullanılan

var async = require('async'); 

rssparser.parseURL(url, options, function(err, out){ 
    async.each(out.items, function(item, callback){ 

     var m = new model({ 
      title: item.title, 
      url: item.url, 
      summary: item.summary, 
      published: item.published_at 
     }) 

     m.save(function(err, result){ 
      callback(null) 
     }); 

    }, function(err){ 
     //we complete the saving we can do stuff here  
    }); 
} 

Bazıları çoğaltılmış ya da olmasın. ayrıca, onu zorlayabileceğiniz bir dizi ile izleyebilirsiniz. Sonuç olarak, kaydettiğiniz öğe sayısını görebilirsiniz.

+0

Hey, teşekkürler, bu hedefe ulaşmak için daha iyi bir yol olabilir. Çok takdir! – Mike

İlgili konular