Node.js - 确保非阻塞呼叫结束

问题描述:

我正在使用pg postgres节点模块与我的数据库进行交互。当我使用pg的API时,代码没有问题。下面是代码的一个例子:我使用​​写解决此迁移脚本命令行实用程序Node.js - 确保非阻塞呼叫结束

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

;然而,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应用程序)的脚本来确保迁移的up()功能将结束之前,我cli脚本整理?我曾尝试使用回调,但似乎不工作。

UPDATE 另一个例子说明了这一点。以下是关于该问题的单元测试(用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. 
    }); 
}); 
+0

你有没有尝试将回调传递给client.query()而不是使用query.on()? – joshuapoehls 2012-07-06 21:04:30

+0

我已经尝试过'pg'的回调语法,在最后传递一个回调以及向'up()'函数添加回调,并在'client.end()'之后调用,并且在这两种情况下,调用'up()'函数的代码继续,超过调用并最终在'up()'之前结束。 – JamesEggers 2012-07-06 21:08:02

+0

这是异步代码的功能。如果你想“等待”继续,你需要让up()调用一个回调,并且只能从该回调继续执行。 – 2012-07-06 21:23:17

看起来你的原剧本有大约program.action(function() {});一个痛点:

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

     // nothing preventing this function from exiting immediately 
    }); 

我周围戳在commander.js文档了一下,couldn”找到任何有关回拨给您的.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变量。但这只是偏好。

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

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