You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何编写兼容中间件与Socket连接的数据库查询函数?

Fixing Your Dual-Purpose Database Query Function

Got it, let's break down why your current approach isn't working and how to fix it. The issue with your myFunc right now is that it returns a middleware function whenever you call it—so when you try to use it outside an HTTP context (like Socket.io), you’re just getting a function that expects req and res, not actually executing the query and returning results.

We need a way to separate the core database logic from the middleware wrapper, so you can reuse the logic in both scenarios. Here's a clean, maintainable approach:

1. Extract the Core Query Logic

First, pull your database query code into a standalone async function (since database operations are almost always asynchronous). This function will handle the actual work and return the results directly:

async function runDatabaseQuery(param1, param2) {
  // Replace this with your actual database query logic
  try {
    const queryResult = await db.query(
      'SELECT * FROM your_table WHERE column1 = ? AND column2 = ?',
      [param1, param2]
    );
    return queryResult;
  } catch (error) {
    // Re-throw the error so the caller can handle it
    throw new Error(`Database query failed: ${error.message}`);
  }
}

2. Create a Middleware Wrapper

Now, make a separate function that wraps this core logic into an Express middleware. This middleware will pull parameters from req (or use passed-in defaults) and send results via res:

function queryMiddleware(param1 = null, param2 = null) {
  return async (req, res, next) => {
    try {
      // Use passed-in params, or fall back to values from req (adjust as needed: req.query, req.body, etc.)
      const finalParam1 = param1 ?? req.query.param1;
      const finalParam2 = param2 ?? req.body.param2;

      const result = await runDatabaseQuery(finalParam1, finalParam2);
      
      // Option 1: Send the result directly as JSON
      res.status(200).json({ success: true, data: result });
      // Option 2: Attach the result to req for downstream middleware
      // req.queryResult = result;
      // next();
    } catch (error) {
      // Pass errors to Express's error-handling middleware
      next(error);
    }
  };
}

3. Use It in Both Scenarios

Now you can use this in both contexts seamlessly:

As Express Middleware

// Use with hardcoded params
app.get('/api/query-fixed', queryMiddleware('value1', 'value2'));

// Use params from the request (e.g., query string or body)
app.post('/api/query-dynamic', queryMiddleware());

Directly in Socket.io (or Any Non-HTTP Context)

// Inside your Socket.io connection handler
io.on('connection', (socket) => {
  socket.on('run-query', async (param1, param2) => {
    try {
      const result = await runDatabaseQuery(param1, param2);
      socket.emit('query-result', { success: true, data: result });
    } catch (error) {
      socket.emit('query-error', { success: false, message: error.message });
    }
  });
});

Bonus: Single Function for Both Use Cases (Optional)

If you prefer a single function that detects its usage context, you can write a flexible wrapper that checks if it's being called as middleware (i.e., receives req and res):

async function flexibleQuery(...args) {
  // Check if we're being called as Express middleware
  const isMiddleware = args.length >= 2 && 
    typeof args[0] === 'object' && args[0].hasOwnProperty('query') && 
    typeof args[1] === 'object' && args[1].hasOwnProperty('json');

  if (isMiddleware) {
    const [req, res, next] = args;
    try {
      const param1 = req.query.param1;
      const param2 = req.body.param2;
      const result = await runDatabaseQuery(param1, param2);
      res.json({ success: true, data: result });
      next?.();
    } catch (error) {
      next?.(error);
    }
  } else {
    // Direct call: args are the query params
    const [param1, param2] = args;
    return await runDatabaseQuery(param1, param2);
  }
}

// Usage examples:
app.get('/api/mixed', flexibleQuery); // As middleware
const directResult = await flexibleQuery('val1', 'val2'); // Direct call

This approach keeps your code DRY, separates concerns, and works reliably in both HTTP middleware and Socket.io contexts.

内容的提问来源于stack exchange,提问作者user_id

火山引擎 最新活动