Node.js - 确保非阻塞调用完成

时间:2012-07-06 20:45:54

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

我正在使用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围绕此迁移脚本编写命令行实用程序;但是,pg代码段的非阻塞调用正在释放命令行界面脚本,以便在完成数据库更新之前完成。以下是一个示例指挥官片段:

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 app)脚本,以确保迁移的up()函数在我的cli脚本完成之前完成?我曾尝试使用回调,但似乎无法正常工作。

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

向上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.
    });
});

2 个答案:

答案 0 :(得分:3)

看起来您的原始脚本在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变量。但这只是偏好。

答案 1 :(得分:0)

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

您可以在此处深入了解代码,了解我们如何执行此操作:https://github.com/WindowsAzure/azure-sdk-for-node/blob/master/lib/cli/cli.js。搜索progress()函数。