Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/368.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 当使用多个路由时,使用express和chokidar热重新加载会导致http头发送错误_Javascript_Node.js_Express - Fatal编程技术网

Javascript 当使用多个路由时,使用express和chokidar热重新加载会导致http头发送错误

Javascript 当使用多个路由时,使用express和chokidar热重新加载会导致http头发送错误,javascript,node.js,express,Javascript,Node.js,Express,我一直在尝试各种热重新加载设置,我遇到的一个是。修改此样板代码作为起点,我在服务器代码中遇到了以下问题: // server.js import chokidar from 'chokidar'; import express from 'express'; const app = express(); // this is the middleware for handline all of my routes app.use(function (req, res, next) { r

我一直在尝试各种热重新加载设置,我遇到的一个是。修改此样板代码作为起点,我在服务器代码中遇到了以下问题:

// server.js
import chokidar from 'chokidar';
import express from 'express';

const app = express();

// this is the middleware for handline all of my routes
app.use(function (req, res, next) {
  require('./server/index')(req, res, next);
  // if I commented out any additional routes, the setup would work fine
  require('./server/foo')(req, res, next);
  require('./server/catch-all')(req, res, next);
});

//this watches the server folder for changes
const watcher = chokidar.watch('./server');

watcher.on('ready', function () {
  watcher.on('all', function () {
    console.log("Clearing /server/ module cache from server");
    Object.keys(require.cache).forEach(function (id) {
      if (/[\/\\]server[\/\\]/.test(id)) delete require.cache[id];
    });
  });
});

app.listen(3000, 'localhost', function (err) {
  if (err) throw err;
  const addr = this.address();
  console.log('Listening at http://%s:%d', addr.address, addr.port);
});
上面是服务器代码,它通过监视chokidar模块的更改来处理清除缓存。如果我在app.use中间件功能(监听每个传入请求)中只需要一条路由,我就可以让它工作。但是,如果有多条路由,则会发生以下错误:

错误[ERR\u HTTP\u HEADERS\u SENT]:发送到客户端后无法设置头

这是关于堆栈溢出的常见问题,但我遇到并尝试过的所有解决方案都没有奏效。我的路由文件如下所示:

//index.js
import express from 'express';

const router = express.Router();

router.get('/', (req, res, next) => {
  res.send("greagrehgarhegrehuh").end();
  return next('router');
});

module.exports = router;
//end of index.js

//foo.js
import express from 'express';

const router = express.Router();

router.get('/foo', (req, res, next) => {
  res.send("foo").end();
  return next('router');
});

module.exports = router;
//end of foo.js

//catch-all.js
import express from 'express';

const router = express.Router();

router.get('*', (req, res, next) => {
  res.send("catch all").end();
  return next('router');
});

module.exports = router;
// end of catch-all.js
除了端点之外,所有三条路线都做相同的事情。到目前为止,我已经显式地调用了end-on-each来结束响应,使用return-next('router')来跳过其余的中间件功能,并且也尝试在没有上述功能的情况下完成它。有没有关于我在这里遗漏了什么来让这一切顺利进行的想法?下面是一个github项目,展示了这个问题

更新

因此,我实际上删除了接下来的通话,并且通过执行以下操作,似乎几乎可以正常工作:

app.use(function (req, res, next) {
  require('./server/index')(req, res, next);
  require('./server/foo')(req, res, next);
}); 

// a second app.use middleware, that does the same 
// as the catch all // * router.get from my original post
app.use(function (req, res, next) {
  app.get('*', (req, res) => res.send('catch all'));
})
// you need to use comma separated routes
app.use(
   dynamic('./server/index'), 
   dynamic('./server/foo')
);

// require the library at runtime and apply the req, res, next arguments
function dynamic(lib) {
  return function (req, res, next) {
    return require(lib).apply(this, arguments)
  }
}
但是,我无法使用第二个应用程序。与其他应用程序一样,使用另一个使用express router的文件require调用。因此,express似乎穿过中间件堆栈,到达*并尝试设置两次头

我需要*的原因通常是,如果用户请求一个不存在的端点,节点将正确显示为cannot GET/。然而,由于某些原因,使用我概述的设置,express将崩溃。我的解决方法是在中间件堆栈的末尾使用*,我只需要使用res.redirect将用户发送回任何地方,但这导致了我在原始帖子中概述的上述问题。所以我不知道该怎么绕过那个

因此,目前我有:

1) 热重新加载不需要路由器.get('*'),但当用户导航到不存在的端点时,express将崩溃


2) 热重新加载适用于app.get(“*”)在第二个app.use调用中,但我不能使用路由器将其移动到单独的文件中。

让我们后退一步,讨论一下中间件

const runMiddleware = (req, res, next) => {
  console.log(`this will run everytime a HTTP request comes in`);
}
假设您有一个运行某种中间件的函数

const runMiddleware = (req, res, next) => {
  console.log(`this will run everytime a HTTP request comes in`);
}
然后在express中使用该中间件:

app.use(runMiddleware);
每次任何(获取、发布、删除等)请求传入时,都会运行此功能

本质上,您正在做下面相同的事情-您正在使用一个函数包装三(3)个路由调用。此函数一次调用所有这些路由,因此在下面的示例中,
res
实际上连续发送3次:

app.use(function (req, res, next) { // runs every time any request comes in
  require('./server/index')(req, res, next); // res sent, ok
  require('./server/foo')(req, res, next); // res sent, err
  require('./server/catch-all')(req, res, next); // res sent, err
}); 
以下是处理路线的基本方法:

const index = require('./server/index');
const foo = require('./server/foo');

app.use('/', index);
app.use('/foo', foo);

// catch everything else
app.use(function (req, res) {
  res.send('catch all');
})

好的,把这个解决方案贴出来,供我将来参考,以防有人碰到这个问题

在与快速开发人员交谈后,事实证明,通过以下组合,这确实是可能的:

app.use(function (req, res, next) {
  require('./server/index')(req, res, next);
  require('./server/foo')(req, res, next);
}); 

// a second app.use middleware, that does the same 
// as the catch all // * router.get from my original post
app.use(function (req, res, next) {
  app.get('*', (req, res) => res.send('catch all'));
})
// you need to use comma separated routes
app.use(
   dynamic('./server/index'), 
   dynamic('./server/foo')
);

// require the library at runtime and apply the req, res, next arguments
function dynamic(lib) {
  return function (req, res, next) {
    return require(lib).apply(this, arguments)
  }
}
对于webpack,这会破坏它,因为您不能将require用作表达式。因此,请使用以下方法来解决这一问题:

function createRoutes(router) {
    const dynamic = (lib) => {
        return function (req, res, next) {
            // let webpack generate a regex expression from this require
            // if we don't you would get a critical dependency warning
            // which would result in the routes not being found
            return require("./src/" + lib + ".js").apply(this, arguments);
        }
    }
    router.use(
        dynamic('index'),
        dynamic('foo'),
    );
    return router;
} 

它在没有热重新加载的情况下工作吗?我不明白您为什么在路由中使用next()?请参阅我上面的更新;试图将其作为评论发布,但太长。您是否查看过express generator?您没有使用
应用程序。请正确使用
,这就是您遇到问题的原因
express generator
将为您提供基本设置并了解其工作原理。我没有,但我可以研究一下。它是否为服务器端提供热重新加载?我在哪些方面没有正确使用app.use?不,它不提供或与热重新加载无关。您有一个热重新加载包,它在express中非常有效。第一个包不会发送两次响应,因为它们都处理不同的路由。只有在同一个app.use中间件堆栈中的catch-all即*时,才会导致该问题。我已经尝试了它的其余部分,这更接近于一个解决方案。但是,foo路径将通过该设置转到foo/foo,而不是/foo。我可以通过在每个路径的路由器文件中使用get(“/”)来解决这个问题。然而,这并不能解释为什么express不允许使用路由器定义一个“一网打尽”的路由。