Nodejs express渲染ejs,如果是首页这种逻辑比较多的页面。用哪种方案好?

Nodejs express渲染ejs,如果是首页这种逻辑比较多的页面。用哪种方案好?

express渲染ejs,如果是首页这种逻辑比较多的页面。用哪种方案好? 一、app.get(’/’,fn1,fn2,fn3,fn(){render})这种next的方式 二、并发执行,然后兼听fn1,fn2,fn3全部完成再render 三、用ajax方式,模板加载后主动取数据渲染 是不是有更好的方案?

6 回复

对于 Node.js 和 Express 渲染 EJS 模板时,处理逻辑复杂的首页(例如需要从多个 API 获取数据、处理复杂的业务逻辑等),选择合适的方案非常重要。以下是对您提出的几种方案的分析以及推荐方案:

方案一:中间件链(next 的方式)

这种方式是 Express 中间件的标准使用方式。它适用于需要按顺序处理多个步骤的情况。

app.get('/', function(req, res, next) {
    fn1(req, res, next);
}, function(req, res, next) {
    fn2(req, res, next);
}, function(req, res, next) {
    fn3(req, res, next);
}, function(req, res) {
    res.render('index', { /* 数据 */ });
});

优点:代码结构清晰,易于理解和维护。 缺点:如果 fn1, fn2, fn3 是异步操作,则可能造成阻塞或回调地狱。

方案二:并发执行,等待所有完成

这种方式适用于需要并行处理多个任务,并在所有任务完成后进行渲染的情况。

const async = require('async');

app.get('/', function(req, res) {
    const tasks = [
        function(callback) { fn1(req, res, callback); },
        function(callback) { fn2(req, res, callback); },
        function(callback) { fn3(req, res, callback); }
    ];
    
    async.parallel(tasks, function(err, results) {
        if (err) return res.status(500).send(err);
        res.render('index', { /* 数据 */ });
    });
});

优点:提高性能,适合并行任务。 缺点:需要引入额外的库如 async

方案三:使用 AJAX

这种方式将部分渲染逻辑移到客户端,减轻服务器负担,但可能导致首屏加载时间变长。

<!-- index.ejs -->
<div id="content"></div>

<script>
fetch('/api/data')
    .then(response => response.json())
    .then(data => {
        document.getElementById('content').innerHTML = renderTemplate(data);
    });
</script>

优点:减少服务器压力,提升用户体验。 缺点:增加客户端复杂度,可能影响 SEO。

推荐方案

并发执行 + async 库:这种方式可以同时利用服务器资源,提高响应速度,又保持代码简洁。推荐使用这种方法,尤其是当你的应用中有很多类似的场景需要处理。

const async = require('async');
app.get('/', function(req, res) {
    const tasks = [
        function(callback) { fn1(req, res, callback); },
        function(callback) { fn2(req, res, callback); },
        function(callback) { fn3(req, res, callback); }
    ];

    async.parallel(tasks, function(err, results) {
        if (err) return res.status(500).send(err);
        res.render('index', { /* 数据 */ });
    });
});

这样既保证了性能,又保持了代码的可读性和可维护性。


fn1,fn2,fn3不再执行完,不能render吧?

使用流程控制模块来控制流程 比如async等

what is this

对于首页这种逻辑较多的页面,可以采用异步并行处理的方式来优化性能和代码可维护性。推荐使用并发执行的方式,确保所有异步任务完成后统一渲染页面。这里可以通过async库或者Promise.all来实现并发执行,这样可以保证首页加载时所有必要的数据都已准备好。

示例代码(使用Promise.all

const express = require('express');
const app = express();
const ejs = require('ejs');

// 定义异步函数fn1, fn2, fn3
async function fetchData1() {
    // 模拟异步操作,例如数据库查询
    return new Promise(resolve => setTimeout(() => resolve({ data: 'data1' }), 500));
}

async function fetchData2() {
    return new Promise(resolve => setTimeout(() => resolve({ data: 'data2' }), 400));
}

async function fetchData3() {
    return new Promise(resolve => setTimeout(() => resolve({ data: 'data3' }), 600));
}

app.get('/', async (req, res) => {
    try {
        const [data1, data2, data3] = await Promise.all([fetchData1(), fetchData2(), fetchData3()]);
        
        // 渲染EJS模板,并传递数据
        res.render('index', { data1, data2, data3 });
    } catch (error) {
        console.error(error);
        res.status(500).send('Internal Server Error');
    }
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

解释

  1. 异步函数fetchData1, fetchData2, 和 fetchData3 是三个模拟的异步数据获取函数。
  2. 并发执行:通过 Promise.all,这三个函数会被并发执行,而不是按顺序执行。当所有函数都完成时,才会继续下一步。
  3. 数据传递:将所有获取的数据传递给 EJS 模板进行渲染。
  4. 错误处理:使用 try...catch 来捕获可能发生的错误,避免服务器崩溃。

这种方式可以显著提高首页加载速度,并保持代码清晰易维护。

回到顶部