I'm currently making a Node.js
server using Express.js
and Typescript
. I have a routes
folder in which I create .ts
files containing routes. One of these files may look something like this:
import { Router, Request, Response } from "express";
export const router: Router = Router();
router.get("/", (_: Request, res: Response) => {
res.json({
message: "Hello world",
});
});
export const path = "/users";
In my main file server.ts
I dynamically add all routes using the exported variables in the routes. This looks something like this:
// set __dirname
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const routesPath: string = path.join(__dirname, "routes");
// register routes
try {
fs.readdirSync(routesPath).forEach(async (file: string) => {
const route: { path: string; router: Router } = await import(
`./routes/${file}`
);
app.use(route.path, route.router);
});
// ! Causes Issue
app.all("*", (_: Request, res: Response) =>
res.status(404).json({
message: "Not found",
status: 404,
})
);
} catch (err) {
console.log(err);
}
In the route below that has the *
route I'm getting an issue where when it is uncommented it overwrites all other routes to itself but the routes work normally when I have it commented out. What may be causing this? I also tried to move the 404
route before registering all routes but that didn't help.
CodePudding user response:
The issue is because of the loop block running asynchronously, even though you have defined app.all("*", ...)
after the forEach
, but it will be executed before forEach
.
So you need to change the forEach
part like below:
await Promise.all(fs.readdirSync(routesPath).map(async (file: string) => {
const route: { path: string; router: Router } = await import(
`./routes/${file}`
);
app.use(route.path, route.router);
}));
app.all("*", (_: Request, res: Response) =>
res.status(404).json({
message: "Not found",
status: 404,
})
);
CodePudding user response:
async function registerRoutes() {
let files = fs.readdirSync(routesPath);
for (let i = 0; i < files.length; i ) {
let file = files[i];
const route = await import(`./routes/${file}`);
app.use(route.path, route.router);
console.log("register ");
}
console.log("final");
app.use("*", (_, res) =>
res.status(404).json({
message: "Not found",
status: 404,
})
);
}