express.js(或类似)应用程序的异步初始化

时间:2016-01-07 16:34:55

标签: javascript node.js asynchronous express web-frameworks

考虑一个示例:我有以下CREATE PROCEDURE NewCustomer ( ) AS BEGIN SELECT MAX(CustID) FROM dbo.Customer; END 应用(请参阅下面的代码段)。我希望在整个应用程序生命周期中有一个与DB的持久连接,以及一个与我自己的服务的持久连接(需要异步调用才能启动)。并且有一些入口点,即不仅可以通过HTTP协议访问我的应用程序。当然,我想避免服务初始化代码重复,并且可能有几个这样的异步初始化服务。

express.js

在上面的代码片段中,当http(或telnet或任何其他)服务器启动时,无法保证/* app.js */ var app = require('express')(); // set views, use routes, etc. var db = require('monk/mongoose/etc')(...); // happily, usually it's a sync operation var myService = require('./myService'); // however, it's possible to have several such services myService.init(function(err, result) { // only here an initialization process is finished! }); module.exports.app = app; /* http_server.js (www entry point) */ var app = require('app'); // create an HTTP server with this app and start listening /* telnet_server.js (other entry point) */ var app = require('app'); // create a Telnet server with this app and start listening 已初始化。

所以,我必须以某种方式重新组织我的应用创建代码。现在我坚持下一个解决方案:

myService

所以,我的问题是:初始化服务的常用方法是什么,需要异步调用才能启动?

2 个答案:

答案 0 :(得分:1)

我建议您将服务的初始化功能合理化,然后以以下方式使用它们:

    @Data
    public class ServiceInfo {
      private String name;
      
      public ServiceInfo() {
      }

      public ServiceInfo(String name) {
        this.name = name;
      }
    }

我使用Promise.all来为您添加多个内部服务的初始化。

推广您的init函数的先决条件是它应该使用错误优先回调机制。您可以在这里Node Official Doc

了解更多信息

希望这有助于您的事业。

答案 1 :(得分:0)

我创建了一个gist here,其中包含我通常用于此任务的代码示例。 (它使用Q promise库,但可以很容易地修改为使用任何其他promises库。)

基本思想是将app骨干描述为一系列异步初始化步骤。每个步骤调用一个或多个异步函数并将结果绑定到名称;一旦为当前步骤解析了所有值,启动过程才会进入下一个初始化步骤,然后后续步骤可以访问前面步骤解析的所有值。这允许轻松描述应用程序中服务和组件的依赖顺序。

例如,骨干可以定义如下:

var app = [
  { s1: startService1 },
  { s2: startService2, s3: startService3 },
  { s4: startService4 }
]

(注意,在每个步骤定义中,只给出了对每个函数的引用; gist中显示的start()函数将以正确的顺序调用每个函数。)

每个 startXxx 变量都是一个函数,它接受一个参数,并返回一个延迟的promise,例如:

function startService4( app ) {
    var s1 = app.s1;
    var s2 = app.s2;
    var deferred = Q.defer();
    // ... start the service, do async stuff ...
    return deferred;
}

该函数的 app 参数表示已配置的应用程序主干,以前的初始化步骤的结果可用作其命名属性。

我在相当复杂的系统中使用了这种模式,并发现它是一种简单,灵活和有效的方法来定义系统的高级结构。