如何在流的末尾退出nodejs,以便将最后的值保存到db,并正确记录

时间:2015-01-07 21:42:40

标签: node.js mongodb mongoose bacon.js

我有一个baconjs流,用于保存mongoose的文章。这是代码:

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

一旦流结束onEnd,我想关闭数据库连接并退出nodejs程序。我想,一旦流结束,我应该等待一段时间,以便将最新的值保存到数据库中。所以我使用setTimeout 15秒并使用db.close

问题是,在标准输出中记录日志stream ended closing in 15 seconds.. 50-60次,为什么?这是退出这样一个程序的好方法吗?

2 个答案:

答案 0 :(得分:1)

您正在stream.onEnd的中添加stream.onValue侦听器。这意味着每次触发onValue时都要添加侦听器。您需要在其他事件侦听器之外添加事件侦听器,以便只添加一次。

有多种方法可以处理异步迭代,以确保在关闭数据库之前保存所有文章值(这个步骤实际上可以通过跳过来逃脱)。

// 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;

如果当前未保存文章且流已结束,则会关闭数据库。如果在当前正在保存文章时流结束,则应在保存该文章后关闭数据库。

答案 1 :(得分: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));

它还可以进一步简化:

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