NodeJS异步函数创建页面加载器

时间:2020-01-13 06:38:57

标签: node.js asynchronous async-await

我知道如果我们在await中有async function,那么该函数将被暂停直到完成await,所以我想知道我们是否可以使用等待时间来创建页面加载器?如果可以的话,请帮助我!谢谢!

我的 app.js 在这里:

const express = require('express');
const app = express();
const mongoose = require('mongoose');
require('dotenv/config');

// set up template engine;
app.set('view engine', 'ejs');

// static file; middleware;
app.use(express.static('public'));
app.use('/post', express.static('/public'));

// middleware;
const homeRoute = require('./controllers/home');
app.use('/', homeRoute);
const postsRoute = require('./controllers/posts');
app.use('/posts', postsRoute);


// connect to mongodb;
mongoose.connect(
    process.env.DB_CONNECTION,
    { useNewUrlParser: true},
    function(){
        console.log('Connected to db');
    }
);

// listen to port;
app.listen(3000);

我的 posts.js 在这里:

const express = require('express');
const router = express.Router();
const Post = require('../models/posts');
const bodyParser = require('body-parser');
const urlencodedParser = bodyParser.urlencoded({extended: false});

router.get('/', function(req, res){
    res.render('post');
});
router.get('/post_render', async function(req, res){
    try {
        let post = await Post.find();             **HERE I WANT TO HAVE A PAGE LOADER**
        res.render('post_render', {data: post});  **DURING WAITING FOR THE DATA TO BE FOUND**
    } catch (err) {
        res.json({message: err});
    }

})

router.post('/', urlencodedParser, async function(req, res){
    let post = new Post({
        title: req.body.title,
        description: req.body.description
    });
    try {
        let savePost = await post.save(); // 
        res.redirect('/posts/post_render');  
    } catch(err){
        res.json({message: err});
    }
});

module.exports = router;

1 个答案:

答案 0 :(得分:3)

浏览器中的旋转圈(通常称为“旋转器”(spinner),显然是“页面加载器”的意思)是客户端的事情。它必须以客户端HTML或Javascript实现。只能在客户端对浏览器中的Ajax调用所请求的路由进行客户端操作,而不对通过重定向或从浏览器到新页面的直接链接所请求的路由进行客户端操作。

问题在于,浏览器一旦开始请求新页面,就会清除当前页面内容(因此您不能将微调框放在旧页面中)。直到足够多的新页面已被解析和显示HTML时,才会显示新页面的内容(一旦一大块自包含的HTML到达,被解析且不会过于依赖其他资源,该页面就会逐步显示尚未加载。

您当前的代码可以执行以下操作:

    let post = await Post.find();             **HERE I WANT TO HAVE A PAGE LOADER**
    res.render('post_render', {data: post});  **DURING WAITING FOR THE DATA TO BE FOUND**

这意味着在您想要显示微调框的时间内,您尚未向浏览器发送任何HTML。因此,浏览器将要做的所有事情都清除了前一页,并坐在那里一个空白页,等待一些可解析的HTML内容到达。由于仅在查找数据库后才发送HTML,因此没有任何内容可以显示微调框的浏览器。因此,这段代码的编写方式将无法显示微调器。

您可以在Ajax调用期间显示微调框。宿主页面显示微调器,进行Ajax调用,然后在Ajax调用完成后隐藏微调器。


我从没有尝试过,但是从理论上讲,该顺序是可能的:

  res.write(partA)
  let post = await Post.find();
  res.render('post_render', {data: post}, function (err, partB) {
      if (err) {
          res.write(partX);
      } else {
          res.write(partB);
      }
      res.end();
  });

在此代码中,您将拥有以下HTML片段:

partA -HTML页面的第一部分,允许浏览器开始解析页面并显示微调框(完全使用HTML或HTML和Javascript)。该页面不能是整个页面,而必须是未完成的部分页面,但是即使在等待页面的其余部分时,浏览器仍可以安全地开始解析和显示。

partB -与partA一起的HTML页面的其余部分。这将隐藏先前的微调器(可能使用Javascript),然后提供页面的其余HTML。 partA + partB将创建一个完全格式化的合法HTML页面。

partX -这是页面的第二部分,与partA一起出现渲染错误时将显示该部分。


另一种可能性是您的路线将发送一个完全格式化的占位符页面,该页面显示内容的外壳并放置微调框。该占位符页面中将包含一些Javascript,该Javascript通过对另一条路由的Ajax调用来请求页面的实际数据或呈现的HTML。当Ajax调用成功时,您的Javascript会将内容插入页面并隐藏微调框。这可能比上面的partA / partB想法简单得多。