如何在Node中创建可重用的函数而不编写样板代码

时间:2016-05-13 15:38:59

标签: javascript node.js express

我使用Express.js作为http服务器。定义了我的所有路线。

大多数端点需要在返回响应之前验证会话。例如。下面的代码分别为系统中的用户和服务列表提供服务:

function getUsers(req, res, next) {
  verifyUser(req, res, next, function () {
      //serve users
  });
}

function getServices(req, res, next) {
  verifyUser(req, res, next, function () {
    //serve services
  });
}

您可能已经注意到有一个验证会话的verifyUser函数。如下所示。

function verifyUser(req, res, next, callback) {
  var sessionKey = req.cookies.sessionKey;
  var user = users.userBySession(sessionKey);
  if (user) {
    callback(req, res, next, user);
  } else {
    res.status(401).send({
      message: 'Unauthorized'
    });
  }
}

正如你所看到的,每当我使用这个函数时,我都会继续传递req,res和next参数以及回调函数。

我尝试使用apply函数使其更容易。改变了我的getUsers函数:

function getUsers(req, res, next) {
  verifyUser
    .apply(null, arguments, function () {
      //serve users
    });
}

这种方法的问题是回调没有传递给verifyUser函数。我并不是真的喜欢在每次调用时将null作为范围传递。

如何通过编写更少更好的代码来实现这一目标?有什么想法吗?

2 个答案:

答案 0 :(得分:0)

您可以使用bind创建“部分功能”:

// create bound responseHelper object
var responseHelper = verifyUser.bind(null, req, res, next);

// usage
responseHelper(getUsersCallback); // same as verifyUser(req, res, next, getusersCallBack);

答案 1 :(得分:0)

我认为您希望将verifyUser转变为中间件功能。

function verifyUser (req, res, next) {
  var user = // yadda yadda session stuff
  if (user) {
    req.user = user; // [1] what you do to the req object here...
  } else {
    return res.status(401).send({ message: "No way Smokey Joe"});
    /**
     * alternatively, do something like

     * var err = new Error("Not authorized");
     * err.statusCode = 401;
     * return next(err);
     * 
     * this will kick off Express' error handling mechanism, 
     *   which you should read about in the docs (see the link below)
     */
  }

  next(); 
  // very important to call next after this verifyUser has done its job
  // if you don't, the next middleware won't go off,
  //   and the request will just hang
}

function getUsers (req, res, next) {
    // [2] will show up on the req object here, assuming you chain these
    // two functions together as middleware
}

app.get("/users", verifyUser, getUsers);
app.get("/services", verifyUser, getServices);

// here's a route that needs no session auth, so no need to verifyUser
app.get("/latest-posts", getLatestPosts); 

当你告诉Express use一个函数或通过get('/my/route', hanlderFun)或某些函数将函数附加到路径路径时,你基本上将handlerFun变成了一个中间件。

您可以根据需要在路线上定义许多中间件作为处理程序,只要您继续调用next,它们就会依次执行。

app.post("/checkout", verifyUser, tallyCart, checkInventory, doPayment, sendInvoice);

next的工作是将控制权从当前的middelware传递到下一个。这是一个对象

您也可以使用next执行其他操作,您应该在文档中阅读这些内容。

http://expressjs.com/en/guide/writing-middleware.html http://expressjs.com/en/guide/using-middleware.html

关于路由的文档也有关于中间件的良好信息:

http://expressjs.com/en/guide/routing.html

要获得额外的功劳,请查看错误处理中间件:

http://expressjs.com/en/guide/error-handling.html