簡體   English   中英

無法迭代數組並保存到mongoose。 回調問題?

[英]Having trouble iterating through array and saving to mongoose. Callback issue?

我正在學習節點,表達,mongo,以及在此過程中,javascript。 我正在嘗試使用rssparser獲取一個功能,獲取故事列表並將其保存到mongoose的mongo數據庫中。

我已經完成了RSS工作,而且我正在重復這些故事,這是我遇到問題的拯救。 我想1)檢查數據庫中是否存在故事,2)如果沒有,請保存。 我想我在處理回調的過程中迷失了方向。 這是我當前的代碼,帶有注釋。

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);
                });
            }
        });

    }
});

當這個運行時,我看到的是很多控制台輸出:

它開始顯示所有故事(許多省略):

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   

然后繼續像(許多省略):

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 }                                                                    

它重復了“即將保存”標題(這是Feed中的最后一個故事),並且它保存了一次故事,就像最后一行所示。

console.log輸出顯示我把它,所有的故事標題輸出在頂部,然后從底部的query.exec()調用內的所有東西。

任何幫助表示贊賞......

這個問題是exec回調中引用的故事將被設置為for循環中迭代的最后一件事,一旦回調將被執行,因為所有執行的函數都引用了相同的實例。變量。

解決這個問題的最簡單方法是簡單地將for循環中的每個東西包裝在您使用參數立即執行的函數中,如下所示:

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]);
    }
});

我沒有測試過這個,但我相信你會發現它會解決你的問題

另一個更簡單,更簡潔,更好的方法是迭代數組上forEach循環中的項目,如果你的平台支持(node.js那個) - 這個版本更漂亮:

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);
                });
            }
        });

    });
});

好吧,節點是事件驅動的服務器,javascript也是事件驅動的,所以你可以異步調用東西。

你需要使用一些異步模式來做你想要的。

首先,如果您使用的是mongoose,您可以利用它的架構類來檢查已存在的項目,而無需再次查詢數據庫:

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是唯一的,因此保存將導致重復錯誤,並且mongoose將不保存查詢。

現在迭代這些項目並保存每個項目,我們需要某種模式,幸運的是我們有異步

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       
    });
}

我們在並行模式下使用async,因為我們不關心某些是否重復。 你也可以用一個數組跟蹤它,你可以推送它錯誤的|| 結果,這樣您就可以看到保存了多少項。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM