【问题标题】:Blocking Node in Script脚本中的阻塞节点
【发布时间】:2015-12-03 19:03:24
【问题描述】:

我正在使用 Node.js 编写在服务器上运行的系统脚本。由于 Node 的异步特性,我的脚本在数据库调用有机会完成之前退出,并且没有任何内容写入数据库。

我使用 Mongoose 作为 ORM 并与 MongoDB 交谈,如果这有什么不同的话。 Node.js 提供 SYNCHRONOUS 方法调用正是出于这个原因,例如:https://nodejs.org/api/child_process.html

我想我的问题是:

1) mongoose 是否提供了一种阻止方法,以便我的脚本进程可以等待数据库调用返回?

2)如果没有,除了类似的方法之外,我还应该考虑其他方法吗:

(function wait () {
   if (!SOME_EXIT_CONDITION) setTimeout(wait, 1000);
})();

3) node 不是编写脚本的最佳工具吗?我喜欢用于 web 应用程序开发的 node,并且可以整天编写嵌套回调或使用 Promise。但是作为一种脚本语言呢?

编辑 ---------------------------------- -

下面是一个快速的脚本示例,可以更清楚地说明情况:

#!/usr/bin/env node
# Please note the above that this is a bash script

var schema = mongoose.Schema({
   // ... attributes ...
});
var model = new (mongoose.model('ModelObject'))();

model['attribute'] = 42;

console.log('This gets printed first');
model.save(function(err) {
  console.log('Nothing in the callback gets printed because callback is never called');
  if(err) { // Can't check for errors because this is never reached
    console.log('This never gets printed to the screen');
    console.log('And consequently nothing is ever saved to mongo');
  } else {
    console.log('This never gets printed either');
  }
});
console.log('This gets printed second');

【问题讨论】:

  • 不清楚您的问题是什么。 “我的脚本在数据库调用有机会完成之前退出”你能详细说明一下吗?分享产生问题的代码并详细描述。
  • 你描述的方法很好,是什么阻止你使用它?
  • 也许保存方法正在引发错误,而您没有捕捉/显示它
  • 数据库连接在哪里??
  • 这个问题可能是由于Mongo连接处理不当造成的。检查这个stackoverflow.com/questions/10156623/…

标签: javascript node.js mongodb asynchronous mongoose


【解决方案1】:

我想你正在寻找这个,看看下面是否对你有帮助。

var mongoose = require('mongoose'),
    model1 = mongoose.model('model1'),
    model2 = mongoose.model('model2');

model1.findOne({"type" : 'Active'}, function err(err, catConfig) {
    if(!err.error){
        //This will execute once above DB call is done!
        model2.findOne(condition).remove(function(err, gAnalysis) {
                //Lines of code that you want to execute after second DB call 
        });
    }
});

【讨论】:

  • 您好,感谢您的回复。当通过 node 命令将 node 作为 Web 应用程序运行时,这似乎可以工作,但是当作为脚本运行时,内部调用将永远不会执行,因为系统在回调有机会被调用之前退出脚本。因此函数“model2.findOne(condition)”永远不会被调用。
  • @ossys:节点的工作方式是,只要有尚未调用的回调,系统就永远不会退出。
【解决方案2】:

如果您的模型未保存,则存在 Mongo 错误。遵循 MongoDB 约定,您必须检查错误:

model.save(function(error, savedItem) {
  if(error) {
    // nothing is saved
  }
});

否则,您是否考虑过使用 Promises?它对于链接事件和更简单的错误处理很有用。

Promise = require('bluebird');
Promise.promisifyAll(mongoose.Query.base);

model.saveAsync().then(function(savedItem) {
  // saved
})
.catch(function(error) {
  // handle error
});

【讨论】:

  • 感谢您的回复...但是由于回调从未被执行,我无法检查错误。脚本在回调被调用之前停止。我进行了编辑,希望能更好地展示这种情况。
【解决方案3】:

我没有看到您打开与数据库的连接,所以大概保存模型实例什么都不做,甚至没有调用带有错误的回调...

我已经测试了以下示例:

test.js

var mongoose = require('mongoose');

var kittySchema = mongoose.Schema({
  name: String
});

var Kitten = mongoose.model('Kitten', kittySchema);

mongoose.connect('mongodb://localhost:27017/test', function (err) {
  if (err) throw err;

  var silence = new Kitten({ name: 'Silence' });
  silence.save(function (err, saved) {
    if (err) throw err;

    console.log('Kitty Silence is saved!');

    mongoose.disconnect(function (err) {
      if (err) throw err;

      console.log('done...');
    });
  });
});

运行 node test.js 将其打印到控制台:

Kitty Silence is saved!
done...

检查我的本地测试数据库显示 Silence 确实保存了。

【讨论】:

    猜你喜欢
    • 2018-01-08
    • 2020-09-22
    • 2012-07-26
    • 2020-11-06
    • 1970-01-01
    • 2019-12-02
    • 2015-10-11
    • 2016-08-05
    • 2014-04-13
    相关资源
    最近更新 更多