【问题标题】:NODEJS how to connect several express.method() via middlewareNODEJS 如何通过中间件连接多个 express.method()
【发布时间】:2017-02-21 10:57:09
【问题描述】:

我使用 express() 构建了多种方法。为简单起见,假设我构建了 2 个 POST() 函数,并且我希望能够自己使用它们,并通过中间件将它们连接起来以进行组合使用。

app.post('/create_obj_1' , function (req,res) {
    //create Object_type_1
    // send Object_type_1 via EXTERNAL API to somewhere
    res.json({{ "statusCode": 200, "message": "OK" }
}
app.post('/create_obj_2' , function (req,res) {
    //create Object_type_2
    // send Object_type_2 via EXTERNAL API to somewhere
    res.json({{ "statusCode": 200, "message": "OK" }
}

我想要一个新的 POST() 可以调用其他两个(但仍然支持独立调用原始 2 我认为可以通过中间件实现,但我不确定如何——这就是我认为新的 POST() 应该是什么样子的——

app.post('/create_obj_all' , function (req,res) {
   //I want to invoke the create_obj_1 & create_obj_2 , check all OK, and finish
    res.json({{ "statusCode": 200, "message": "OK" }
}

我不确定在这种情况下如何处理中间件的使用。

最重要的是-如何将它们连接起来以相互使用资源?假设 EXTERNAL API 从 obj_1 创建中返回一些值,我想在 obj_2 post() 函数中使用它..

我尝试在 middlware_1 中使用 request() 的伪代码 -

var middle_1 = function (req, res, next) {
        req.middle_1_output  = {
            statusCode : 404,
            message : "fail_1"
        }
        var options = { 
                method: 'PUT', url: `EXTERNAL_API`, headers: 
                { 
                    'cache-control': 'no-cache',
                    'content-type': 'application/x-www-form-urlencoded',
                    apikey: `KEY`
                }
            };
        request(options, function (error, response, body) {
            if (error) throw new Error(error);

            // CODE THAT DO SOMETHING AND GET INFORMATION

            // OLD WAY OF res.send here , to allow using in post.POST() was - res.status(200).send(body);

            //res.status(200).send(body);
            req.middle_1_output.statusCode = 200;
            req.middle_1_output.message = "hello world";
        });
     next(); // trigger next middleware
}

【问题讨论】:

  • 您必须像我在第二个示例中所做的那样,从回调中调用next。在您的情况下,在完成 request 之前调用下一个中间件。
  • Hey Blaze ,我认为它开始起作用了,但是我遇到了一个问题,因为我在 middleware_1 中使用了 2 request() (一个接一个),所以我想调用下一个( ) 在第一个 request() 结束时,为第二个 request() 造成问题,因为当我尝试在第二个结束时为其分配一个值时,我收到 req.middle_1_output.statuscode is 'undefined' 的错误要求()。我是否需要将 middleware_1 中的第一个 request() 本身也变成中间件?
  • 更新你的问题,我将通过编辑我的最后一个答案来回答。

标签: node.js express middleware


【解决方案1】:

鉴于当前的示例,除非您稍微调整前两条路由的中间件,否则我认为您无法做到:

var middleware1 = function(req, res, next) {
  //create Object_type_1
  // send Object_type_1 via EXTERNAL API to somewhere

  next(); // calling next() triggers the next middleware
};

var middleware2 = function(req, res, next) {
  //create Object_type_2
  // send Object_type_2 via EXTERNAL API to somewhere

  next(); // calling next() triggers the next middleware
};

/**
 * This middleware is only used to send success response
 */
var response_success = function(req, res) {

    res.json({ "statusCode": 200, "message": "OK" });
}

app.post('/create_obj_1', middleware1, response_success);

app.post('/create_obj_2', middleware2, response_success);

app.post('/create_obj_all', middleware1, middleware2, response_success);

注意,这是我从您的示例中得出的一个非常简单的解决方案。实际的实现将取决于每个中间件期望的输入以及它们生成的输出。与这里不同的是,发送响应也可能有不同的中间件。

第二部分解决您问题的第二部分,如果我没听错,您希望将输出从middleware1 传递给middleware2。在调用next(); 之前,您可以简单地将输出附加到req 对象。像这样:

var middleware1 = function(req, res, next) {

  // do something

  some_external_api_call(function(error, data) {

    if (error) {
      // handle the error yourself or call next(error);
    } else {

      req.middleware1_output = data; // set the output of the external api call into a property of req
      next();
    }
  });
};

var middleware2 = function(req, res, next) {

  // check to see if the middleware1_output has been set 
  // (meaning that the middleware has been called from /create_obj_all )
  if (req.middleware1_output) {

    // do something with the data

  } else {

    // handle scenario when /create_obj_2 is called by itself

  }

  next(); // calling next() triggers the next middleware
};

请注意您必须如何考虑从POST /create_obj_all 或直接从POST /create_obj_2 调用middleware2 的两种情况。

第三部分您应该在回调中调用next。请参阅我上面的示例。这是由于 javascript 的异步/非阻塞特性。

function middleware(req, res, next) {

    // do something

    call_1st_external_api(some_options, function(error, data) {

        // executed after call_1st_external_api completes

        req.output_of_1st_external_api = data; // store the data of this api call for access from next middleware

        next(); // calls the next middleware

        // nothing here will be executed as next has already been called
    });

    // anything here will be executed before call_1st_external_api is completed
    next(); // this will call the next middleware before call_1st_external_api completes
}

要在同一个中间件中处理两个外部 API,您必须嵌套它们(或使用异步或承诺):

function middleware(req, res, next) {

    // do something

    call_1st_external_api(some_options, function(error1, data1) {

        // executed after call_1st_external_api completes

        req.output_of_1st_external_api = data1; // store the data of this api call for access from next middleware

        // executed after call_2nd_external_api completes

        call_2nd_external_api(some_options, function(error2, data2) {

            req.output_of_2nd_external_api = data2; // store the data of this api call for access from next middleware

            next();
        });

        // anything here will be executed before call_2nd_external_api is completed
    });

    // anything here will be executed before call_1st_external_api is completed
}

你必须像我在第二部分中展示的那样处理上面的所有错误,为了简单起见,我没有在上面的例子中展示。

【讨论】:

  • 嗨 blaze,非常感谢。我会尽快尝试的。
  • 当然,Blaze,我会的。无论如何,我尝试了这个解决方案,但我得到一个错误,我认为这是由于每个中间件中 res.send 的句柄缺失。这是我得到的错误 - throw new Error('Can\'t set headers after they are sent.');问题在于: 1. 在我的每个中间件中,都使用了 request() 模块来调用外部 API。 2.在请求回调函数的最后,我现在有这行:res.status(200).send(body);问题是,我应该如何改变它?有什么想法吗?
  • 不要从每个中间件调用res.send,而是调用next。制作一个单独的中间件,仅用于调用 res.send 并像我在上面的示例中那样附加它。
  • 看到我在第一个示例中的 response_success 中间件处理发送响应 (res)。
  • 嗨 Blaze - 谢谢你的解释。我很抱歉,但我的结果并没有增加(可能我遗漏了一些东西) - 例如,关于如何从我的 middleware_1 中的 request(callback () ) 方法传输数据 - req.middleware_output_1 无法通过回调,因为 request.callback 调用是这样的 - request(options, function (error, response, body) {...}) 所以“req”没有被访问和更新......我错过了什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-23
  • 2014-09-16
  • 1970-01-01
相关资源
最近更新 更多