0

我正在编写一个中间件,它将执行一系列操作。序列完成后,我希望中间件调用 next()。从这一点上中间件是多余的。我编写了以下代码:(这里的动作序列通过调用 setTimeout 来模拟):

function myMiddleware(req, res, next){

   console.info("inside myMiddleware");

   if (actionDone) {
       console.info("middleware redundant. ActionDone, calling next");
       next();
   }

   setTimeout(doneWaiting, 30000);

   function doneWaiting(){
      actionDone = true;
      next();
   }
}

此代码将不起作用,因为如果在操作完成之前有多个请求到达,则会一次又一次地调用 setTimeout。我希望 setTimeout 只被调用一次,并且只有在它完成后,我才想对迄今为止到达的所有请求调用 next() 。

实现这一目标的最佳方法是什么?

谢谢,李

4

2 回答 2

1

如果我理解正确,您想在任务完成后执行任务并处理所有请求?在那之前他们会等吗​​?

所以这是不可扩展的方式:

var EventManager = new require("events").EventEmitter( );
var actionDone = "start";

function myMiddleware(req, res, next){

   console.info("inside myMiddleware");
   var handler = function( ) {
       console.info("middleware redundant. ActionDone, calling next");
       next();
   };

   if (actionDone === "finished" ) {
       handler( );
       return;
   }

   EventManager.once( "finished", handler );

   if (actionDone !== "working") {
       actionDone = "working";
       function doneWaiting(){
          actionDone = "finished";
          EventManager.trigger( "finished" );
       }
       setTimeout(doneWaiting, 30000);
   }
}

显然它是不可扩展的,因为你不能EventManager在机器之间共享对象。为了在机器之间做到这一点,您可能必须从主服务器向所有其他服务器发出请求并以类似方式处理请求。

警告:您尝试做的事情看起来是一个非常非常糟糕的主意。毕竟请求不应该相互依赖。这很容易导致服务器崩溃。

于 2012-10-25T13:38:46.343 回答
0

actionDone变量设置为req, 这样

function myMiddleware(req, res, next){

console.info("inside myMiddleware");

if (req.actionDone) {
    console.info("middleware redundant. ActionDone, calling next");
    next();
}

setTimeout(doneWaiting, 30000);

function doneWaiting(){
   req.actionDone = true;
   next();
}

}

于 2012-10-25T20:38:16.673 回答