2015-01-07 7 views
0

mongoose과 함께 기사를 저장하는 데 사용하는 baconjs 스트림이 있습니다. 여기 코드는 다음과 같습니다 스트림이 onEnd을 종료스트림 끝에서 nodej를 종료하는 방법 마지막 값이 db에 저장되고 올바르게 기록됩니다.

function main() { 
    db.once('open', function(callback) { 
    console.log('db connection successs'); 
    console.log('stremaing page ' + page); 

    var stream = readSite(page); 
    stream.onValue(function(article) { 
     try { 
     article = toArticleModel(article); 
     } catch (e) { 
     console.error(e); 
     } 
     article.save(function(err, article) { 
     if (err) { 
      console.error('Save Error: ' + err); 
     } else { 
      console.log('saved ' + article.publishedDate + " " + article.author.name + " " + article.title); 
     } 
     }); 

     stream.onError(function(err) { 
     console.error('Stream Error: ' + err); 
     }); 

     stream.onEnd(function() { 
     console.log('stream ended closing in 15 seconds..'); 
     setTimeout(function() { 
      db.close(); 
     }, 15 * 1000); 
     }); 
    }); 
}); 

되면, 나는 DB 연결을 닫고 nodejs 프로그램을 종료합니다. 일단 스트림이 끝나면 최신 값이 db에 저장되도록 잠시 기다려야한다고 생각했습니다. 따라서 setTimeout을 15 초 동안 사용하고 db.close을 사용합니다.

문제는 로그 stream ended closing in 15 seconds..이 표준 출력에서 ​​50-60 번 기록된다는 것입니다. 이유는 무엇입니까? 그런 프로그램을 종료하는 좋은 접근 방법입니까?

답변

1

의 의 stream.onValuestream.onEnd 청취자를 추가하고 있습니다. 즉, onValue이 트리거 될 때마다 수신기를 추가하고 있음을 의미합니다. 다른 이벤트 리스너 외부에 이벤트 리스너를 추가하여 한 번만 추가하면됩니다.

DB를 닫기 전에 모든 기사 값이 저장되도록 비동기 반복을 처리하는 다양한 방법이 있습니다 (실제로 건너 뛸 수있는 단계).

// initialize savingArticles to 0 

savingArticles++; 
article.save(function (err, article) { 
    savingArticles-- 
    if (streamEnded && !savingArticles) 
    db.close(); 

stream.onEnd(function() { 
    if (!savingArticles) 
    db.close(); 
    else 
    streamEnded = true; 

기사가 현재 저장 중이 아니며 스트림이 종료 된 경우 DB를 닫습니다. 기사가 현재 저장되는 동안 스트림이 종료되면 기사를 저장 한 후에 DB를 닫아야합니다.

+1

입니다 FRP를 사용할 때 잘못된 코드의 표시. Roman Pominov의 대답에서'flatMap'과'fromNodeCallback'을 사용하는 것이 훨씬 낫습니다. – OlliM

1

나는 이것에 대한 .fromNodeCallback.flatMap를 사용하려고 것 :

stream = stream.flatMap(function(article) { 

    try { 
    article = toArticleModel(article); 
    } catch (e) { 
    return new Bacon.Error('toArticleModel error: ' + err); 
    } 

    return Bacon.fromNodeCallback(function(callback) { 
    article.save(function(err, article) { 
     if (err) { 
     callback('Save Error: ' + err); 
     } else { 
     callback('saved ' + article.publishedDate + " " + article.author.name + " " + article.title); 
     } 
    }); 
    }); 

}); 

stream.onError(console.error.bind(console)); 
stream.onValue(console.log.bind(console)); 
stream.onEnd(db.close.bind(db)); 

또한 더 단순화 할 수있다 : 가변 상태 (변수`savingArticles`,`streamEnded`)를 사용하여

stream = stream.flatMap(function(article) { 

    try { 
    article = toArticleModel(article); 
    } catch (e) { 
    return new Bacon.Error(err); 
    } 

    return Bacon.fromNodeCallback(article, "save") 
    .map(function() { 
     return "saved " + article.publishedDate + " " + 
     article.author.name + " " + article.title; 
    }); 

}); 

stream.log(); 
stream.onEnd(db.close.bind(db));