ejs async true with node Express

浪尽此生 提交于 2021-01-24 11:29:48

问题


I want to call some of my functions which are asynchronous to be called from within my ejs files.

Like I have this functions set as my app.locals.someFunction

async someFunction(param){
  let data = await someAsyncStuff();
  // &  other things
  return data;
}

and I want to use it inside ejs file as below:

<%
let data = await someFunction()
for(let x of data){%>

   <li><%=x%></li>

<%}%>

This is possible with ejs if {async:true} is passed as an option. But where exactly should I pass this when my view engine setup is like the following?


//view engine setup
app.engine ('.html', ejs.renderFile);
app.set ('view engine', 'html');


回答1:


instead res.render()

const ejs = require('ejs');
const html = await ejs.renderFile(view, data, {async: true});
res.send(html);

every include with await

<body>
    <%- await include(pageView);%>
</body>

async now fine

<%
let data = await collection.find().toArray();

for(let x of data){%>

   <li><%=x%></li>

<%}%>



回答2:


You have to pass the argument async into your render() function call as opts. E.g.

res.render(view, {.., async:true, ... }...) 



回答3:


For people who are still trying to figure out how to implement async ejs templates, I am listing my complete solution below:

In your main app file (app.js)

// app.js
// Set ejs as view engine
app.set('view engine', 'ejs');

let ejsOptions = {
  // delimiter: '?', Adding this to tell you do NOT use this like I've seen in other docs, does not work for Express 4
  async: true
};

// The engine is using a callback method for async rendering
app.engine('ejs', async (path, data, cb) => {
  try{
    let html = await ejs.renderFile(path, data, ejsOptions);
    cb(null, html);
  }catch (e){
    cb(e, '');
  }
});

Now for your route responses...

app.route('/login')
  .get( async (req, res) =>{
      // layout.ejs is my version of blocking. I pass the page name as an option to render custom pages in the template
      return await res.render(`layout.ejs`, { page : 'login' }, (err, html) => standardResponse(err, html, res));
})

I user the function standardResponse() in the callback for both readability and so I have to write less lines. The function works like this...

const standardResponse = (err, html, res) => {
  // If error, return 500 page
  if (err) {
    console.log(err);
    // Passing null to the error response to avoid infinite loops XP
    return res.status(500).render(`layout.ejs`, { page : '500', error: err }, (err, html) => standardResponse(null, html, res));
  // Otherwise return the html
  } else {
    return res.status(200).send(html);
  }
}

And viola! Asynchronous ejs rendering.



来源:https://stackoverflow.com/questions/60203249/ejs-async-true-with-node-express

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!