【问题标题】:Object oriented design in Node.jsNode.js 中的面向对象设计
【发布时间】:2012-12-30 14:42:04
【问题描述】:

我正在为 Node.jsasync 流而苦苦挣扎。假设您有以下课程:

function myClass() {
  var property = 'something';
  var hasConnected = false;

  this.connect = function(params) {
    //Some logic that connects to db and in callback returns if the connection is successful
    connectToSomeDB('ConnectionString', function(connectionResult) {
      hasConnected = connectionResult
    })
  };

  this.get = function(params) {
    if(hasConnected) {
      DoGetOperation() //
    }
    else {
      //Another question. What should be done here. Call the connect again?
    }
  }
}

考虑到 Javascript 和 Node 结构,我当然认为我的设计存在一些重大问题,但我无法找到解决办法,因为 connect 必须调用才能使任何操作正常工作。但是当我在操作后进行一些日志记录时:

brandNewObject = myClass();
brandNewObject.connect();
brandNewObject.get();

我观察到 get 函数在获取全局 isConnected 变量之前被调用。在不违背 Node 的异步结构的情况下,我能做些什么来完成这项工作?

理想情况下,我正在寻找的解决方案实际上是在内部处理“连接”,而不是定义回调“外部类”

【问题讨论】:

    标签: javascript performance oop node.js modularity


    【解决方案1】:

    你必须使用回调。

    function myClass() {
      var property = 'something';
      var hasConnected = false;
    
      // added second parameter
      this.connect = function(params, callback) {
        //Some logic that connects to db and in callback returns if the connection is successful
        connectToSomeDB('ConnectionString', function(connectionResult) {
          hasConnected = connectionResult;
          // Now call the callback!
          callback();
        })
      };
    
      this.get = function(params) {
        if(hasConnected) {
          DoGetOperation() //
        }
        else {
          //Another question. What should be done here. Call the connect again?
        }
      }
    }
    brandNewObject = myClass();
    brandNewObject.connect({}, function () {
      // this function gets called after a connection is established
      brandNewObject.get();
    });
    

    【讨论】:

    • 非常感谢您的回答。但这有点违背我正在寻找的模块化。原因是brandNewObject 将在整个项目中使用。因此会有多个'get'和'set'。因此,如果我想执行一项操作,我必须为每个函数进行连接,而不是进行一次连接,然后在全局范围内使用它。另外,myClass 的目标是成为一个 redisClient,所以我无法连接每个函数,因为它会显着增加客户端的数量
    • 我知道两种处理node.js异步流的方法。第一个是按照我的建议使用回调,第二个是使用 Promises。两者都不同于您可能习惯的“函数返回值,然后我可以使用”流程(您不应该希望在 node.js 应用程序中使用这种流程)。要了解有关承诺的更多信息,我建议使用 Q (github.com/kriskowal/q)
    【解决方案2】:

    为您的connect 方法添加一个回调参数。

      this.connect = function(params, callback) {
        //Some logic that connects to db and in callback returns if the connection is successful
        connectToSomeDB('ConnectionString', function(connectionResult) {
          hasConnected = connectionResult;
    
          // Call the callback provided
          callback(params);
        })
      };
    

    你可以这样称呼它:

    brandNewObject = myClass();
    brandNewObject.connect({}, function(/* optionally, "params" */) {
        brandNewObject.get();
    });
    

    【讨论】:

      【解决方案3】:

      对此有不同的解决方法。

      一种简单的方法类似于你正在做的事情

      this.get = function(params) {
          if (hasConnected) {
              DoGetOperation(params);
          } else {
              //here you can check the status of the connect. if it is still in 
              //progress do nothing. if the connection has failed for some reason
              //you can retry it. Otherwise send a response back indicating that the
              //operation is in progress.
          }
      }
      

      另一种方法可能是为您的 get 函数使用相同的异步回调机制,这会将您的方法签名更改为类似的内容。

      this.deferredOperations = new Array();
      
      this.get = function(params, callback) {
          if (hasConnected) {
             //using a callback as an optional parameter makes the least 
             //impact on your current function signature. 
             //If a callback is present send the data back through it, 
             //otherwise this function simply returns the value (acts synchronously).
             if (callback !== null) {
               callback(DoGetOperation(params));
             } else {
               return DoGetOperation(params);
             }
          } else {
             this.deferredOperations.push([params,callback]);
          }
      }
      
      //connect changes now
      this.connect = function(params) {
      //Some logic that connects to db and in callback returns if the connection is successful
      connectToSomeDB('ConnectionString', function(connectionResult) {
        hasConnected = connectionResult;
        if (hasConnected && this.deferredOperations.length > 0) {
          for (var i=0; i < this.deferredOperations.length; i++) {
            var paramFunction = this.deferredOperations.pop();
            var params = paramFunction[0];
            var func = paramFunction[1];
            DoAsyncGetOperation(params, func); //Need to write a new function that accepts a callback
          }
        }
      })
      };
      

      HTH

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-01-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-29
        • 1970-01-01
        相关资源
        最近更新 更多