自定义中间件开发:如何在回调参数中添加变量与方法
Let's break down why you're seeing that error and how to fix it—this is a common pattern in middleware frameworks like Express, so once you understand the core idea, it'll click.
The Root of the Problem
Right now, when you call server.get('/', (req, res) => { ... }), your server's get method isn't actually creating an instance of your Response class and passing it into the callback. That's why res is undefined when you try to call res.useFile()—the parameter exists in your callback signature, but nothing is being passed to it.
Express works because its internal request handler creates req and res objects (with all those handy methods like res.send() or res.json()) automatically, then passes those instances to your route callback. You need to replicate that behavior in your custom server/middleware.
Step 1: Update Your Server to Pass Response Instances
First, let's assume you have a Server class (since you're using server.get()). You need to modify its get method to store routes, and add a request handler that creates a Response instance when a request matches a route, then passes it to your callback.
Here's a simplified example:
const fs = require('fs').promises; // Use promise-based fs for async/await class Response { constructor() { // Add any internal state you need here (like status codes, headers) } /** * @param {string} path - The URL to fetch * @param {string} filePath - Path to the local file to send */ async useFile(path, filePath) { // Fix: Use promise-based readFile to get file data properly const fileData = await fs.readFile(filePath); const fetchRes = await fetch(path, { method: 'GET', body: fileData, headers: { 'Content-type': 'text/html' } }); // Fix: Don't stringify the Response object directly—use its methods to parse data return fetchRes.json(); // Or fetchRes.text() if you need HTML } } class Server { constructor() { this.routes = []; // Store registered routes } // Register a GET route get(path, callback) { this.routes.push({ method: 'GET', path, callback }); } // Simulate handling an incoming request (you'd hook this up to an HTTP server in real code) async handleRequest(incomingReq) { // Match the incoming request to a registered route const matchedRoute = this.routes.find(route => route.method === incomingReq.method && route.path === incomingReq.url ); if (matchedRoute) { // Create your custom Response instance const res = new Response(); // Pass the real request object and your Response instance to the callback await matchedRoute.callback(incomingReq, res); } else { // Handle 404 if no route matches console.log('404 Not Found'); } } } // Usage example const server = new Server(); server.get('/', async (req, res) => { try { const data = await res.useFile('https://your-target-url.com', './index.html'); console.log('Fetch result:', data); } catch (err) { console.error('Error:', err); } }); // Simulate an incoming request (in real code, use http.createServer) server.handleRequest({ method: 'GET', url: '/' });
Step 2: Fix the useFile Method
I also fixed a critical issue in your useFile function:
- You were using the callback version of
fs.readFile, which doesn't return the file data directly (it passes it to the callback). Usingfs.promises.readFilelets you useawaitto get the data properly. - You tried to
JSON.stringify()the rawfetchResponse object—you need to use methods likeres.json()orres.text()to parse the response body.
Key Takeaway
Middleware frameworks like Express don't magically make req and res available—they explicitly create instances of their request/response classes and pass them to your callbacks. Your job is to replicate that flow in your custom server:
- Register routes with callbacks.
- When a request comes in, create your
Responseinstance. - Pass the request and response instances to the matched route's callback.
That's how you'll get access to res.useFile() without the undefined error.
内容的提问来源于stack exchange,提问作者User not found

