【问题标题】:Node.js - Ensuring a non-blocking call finishesNode.js - 确保非阻塞调用完成
【发布时间】:2012-07-07 08:08:51
【问题描述】:

我正在使用pg postgres 节点模块与我的数据库进行交互。当我使用 pg 的事件 API 时,代码可以正常工作。下面是代码示例:

Migration.js

 exports.up = function(logger){
    var pg = require("pg")
        , connectionString = //process.env.CONNECTIONSTRING
        , client = new pg.Client(connectionString);

    client.connect();

    var cmd = "CREATE TABLE users( "
                + "id SERIAL NOT NULL, "
                + "firstName VARCHAR(50) NOT NULL, "
                + "lastName VARCHAR(50) NOT NULL, "
                + "CONSTRAINT pk_userid PRIMARY KEY (id) "
                + ")";

    var query = client.query(cmd);

    query.on("end", function(){
        client.end();
            logger.log("complete");
    });
};

我正在使用commander.js 围绕此迁移脚本编写命令行实用程序;但是,pgsn-p 的非阻塞调用正在释放命令行界面脚本,以便在数据库更新完成之前完成。下面是一个示例指挥官 sn-p:

MyCliTool

var program = require('commander');

program
    .version('1.0.2');

program
    .command("up")
    .description("Migrates up")
    .action(function(){
        require("../src/migration").up();
    });

// Additional code removed for brevity

是否可以更改迁移(或commander.js 应用程序)脚本以确保迁移的up() 函数将在我的cli 脚本完成之前完成?我尝试过使用回调,但这似乎不起作用。

更新 另一个例子来说明这一点。以下是关于该问题的单元测试(使用mocha 编写)。

Up-test.js

describe("feature", function(){
    it("should finish", function(){
        var logger = {};
        var finished = false;
        logger.log = function(){finished = true;};

        var migration = require("../src/migration.js");
        migration.up(logger);
        assert(finished, "function didn't finish"); // finished is false when this gets called.
    });
});

【问题讨论】:

  • 您是否尝试过将回调传递给 client.query() 而不是使用 query.on()?
  • 我试过pg的回调语法,在最后传入一个回调,并在up()函数中添加一个回调并在client.end()之后调用,在这两种情况下,调用up() 函数的代码继续执行,通过调用并最终在up() 之前完成。
  • 这就是异步代码的运作方式。如果您想“等待” up 继续,您需要让 up() 调用回调,并且只从该回调继续执行。
  • 你的 up-test.js 看起来有点错误:assert(finished); 应该在你的 logger.log 函数内,或者在不会立即执行的东西内。 Mocha 为您提供了一个异步测试回调,您也必须使用它:it("should finish", function (completedCallback) { }); 请参阅visionmedia.github.com/mocha/#asynchronous-code

标签: postgresql node.js javascript-events flow-control


【解决方案1】:

尝试设置计时器 (http://nodejs.org/api/timers.html)。我们在 Azure CLI 工具中执行此操作,以便在您执行长时间运行的操作时运行微调器。

您可以在此处深入研究代码以了解我们是如何做到的:https://github.com/WindowsAzure/azure-sdk-for-node/blob/master/lib/cli/cli.js。搜索 progress() 函数。

【讨论】:

    【解决方案2】:

    看起来您的原始脚本在program.action(function () {}); 附近有一个痛点:

    program
        .command("up")
        .description("Migrates up")
        .action(function(){
            require("../src/migration").up();
    
            // nothing preventing this function from exiting immediately
        });
    

    我在commander.js 文档中浏览了一下,找不到任何关于为您的.action() 程序提供回调的信息。如果我正在编写它,代码将如下所示:

    program
        .command("up")
        .description("Migrates up")
        .action(function (completedCallback) {
    
            require("../src/migration").up(function () {
                // migration is complete
                completedCallback();
            });
    
        });
    

    不过,您与 postgre 相关的脚本看起来不错。一个有点不相关的注释可能是让require("../src/migration").up(); 返回一个require("events").EventEmitter 的实例并发出您想要查看的事件,而不是使用logger 变量。但这只是偏好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-02
      • 2013-06-24
      • 1970-01-01
      • 2015-07-06
      • 2014-03-23
      • 1970-01-01
      相关资源
      最近更新 更多