在使用 express 呈现页面之前等待所有 mySql 请求完成

Posted

技术标签:

【中文标题】在使用 express 呈现页面之前等待所有 mySql 请求完成【英文标题】:Waiting for all mySql requests to finish before rendering page with express 【发布时间】:2021-07-04 16:45:37 【问题描述】:

我有一个 node.js 服务器,它在用户选择他想要查看状态的储物柜类型后查询数据库。储物柜有多种状态:殖民、非更新、免费、占用。获取这些类别中的任何一个都是通过特定请求完成的。

我想要的是,如果用户选择所有选项,能够执行所有请求并将所有行放入数组中,然后用它呈现网页。问题是异步的,```connection.query````没有按顺序返回,不知道怎么解决。

app.get('/admin/sites/lockers/*', function (req, res) 
    console.log("GET /admin/sites/lockers");
    let parsedQs = querystring.parse(url.parse(req.originalUrl).query);
    console.log(parsedQs);
    let resultArray = [];

    if(parsedQs['colonised']) 
        let query = fs.readFileSync('./sql/colonised_lockers.sql', 'utf8');
        connection.query(query, function (err, results, fields) 
            resultArray.push(results[0]);
            console.log("colonized :", resultArray);
        );
    

    if(parsedQs['non_renewed']) 
        let query = fs.readFileSync('./sql/non_renewed_lockers.sql', 'utf8');
        connection.query(query, function (err, results, fields) 
            resultArray.push(results[0]);
            console.log("non_renewed :", resultArray);
        );
    

    if(parsedQs['free']) 
        let query = fs.readFileSync('./sql/free_lockers.sql', 'utf8');
        connection.query(query, function (err, results, fields) 
            resultArray.push(results[0]);
            console.log("free :", resultArray);
        );
    
    console.log("finally :", resultArray);
    res.render('admin/lockerView.ejs', lockers : resultArray );
);

【问题讨论】:

你读过关于等待等的nodejs.dev/learn/… 【参考方案1】:

您可以尝试在您用于连接数据库的工具的文档中找到基于Promise 而不是callback 的方法。但是您也可以将您的connection.query 包装到Promise 中并使用async await 以便在处理程序中具有“类似同步”流。比如:

function makeDBQuery(query) 
  return Promise((resolve, reject) => 
    connection.query(query, function (err, result) 
      err ? reject(err) : resolve(result);
    );
  );


app.get('/admin/sites/lockers/*', async function (req, res) 
  console.log('GET /admin/sites/lockers');
  const parsedQs = querystring.parse(url.parse(req.originalUrl).query);
  console.log(parsedQs);
  const resultArray = [];

  if (parsedQs['colonised']) 
    const query = fs.readFileSync('./sql/colonised_lockers.sql', 'utf8');
    const result = await makeDBQuery(query);
    resultArray.push(result);
  

  if (parsedQs['non_renewed']) 
    const query = fs.readFileSync('./sql/non_renewed_lockers.sql', 'utf8');
    const result = await makeDBQuery(query);
    resultArray.push(result);
  

  if (parsedQs['free']) 
    const query = fs.readFileSync('./sql/free_lockers.sql', 'utf8');
    const result = await makeDBQuery(query);
    resultArray.push(result);
  
  console.log('finally :', resultArray);
  res.render('admin/lockerView.ejs',  lockers: resultArray );
); 

当然你需要一些错误处理程序,你可以将重复的代码移动到附加函数中,但这是另一回事)

【讨论】:

以上是关于在使用 express 呈现页面之前等待所有 mySql 请求完成的主要内容,如果未能解决你的问题,请参考以下文章

在 forEach 之后使用 Promise.all() 渲染 NodeJS 页面之前等待 Firebase 数据加载

使用 JWT 保护 Express 路线

在渲染网页之前等待字体加载

如何在自定义 Express 服务器上呈现 Next JS 页面

Node.js/Express - 找不到页面时呈现错误

如何一个接一个地渲染多个html文件?