Express.js:res.render()在包含在promise链

时间:2017-06-05 17:06:23

标签: node.js express mongoose promise ejs

我最近开始重构旧的回调地狱路线以使用promises。 (注意:重构不完整所以下面的一些代码很难看)

这样做会破坏我的res.render()功能。

  • 我正在使用EJS作为渲染引擎。
  • 我的大多数承诺链都是基于MongoDB / Mongoose查询构建的。

基本的应用程序结构是一个复杂的调查/测验,可以将用户分为不同的类别。它存储它们的信息并在最后呈现自定义EJS页面。以下是最终通话的工作原理:

         mongoose.model('Result')
             .findOne({quizId: req.query.id})
             .then(getPageData)
             .then(renderPage)
             .catch(errorHandler)

理论上很简单。

相关功能:

    let getPageData = (mongooseResult) => {

      let resultsPage;
      let analyticsData;

      if (mongooseResult.answers.section1.question1.answer != null && mongooseResult.answers.section1.question1.answer != undefined){
          let resultsPage = WP.getPage(wp_pages_data, 'slug', mongooseResult.coreFit);
          let analyticsData = {
            quizId: mongooseResult.quizId,
            coreFit: mongooseResult.coreFit,
            secondFit: mongooseResult.secondFit,
            degree: mongooseResult.answers.section1.question1.answer,
            year: mongooseResult.answers.section1.question2.answer,
            concentration: mongooseResult.answers.section1.question3.answer,
            views: mongooseResult.views,
          }

        mongooseResult.views++;
        mongooseResult.save();

        return [resultsPage, analyticsData, mongooseResult];
      } else {
        throw new Error('S1Q1 IS UNDEFINED');
      }
    };
    let renderPage = ([resultsPage, analyticsData, mongooseResult]) => {
      if (resultsPage != null && resultsPage != undefined){

        // WHY IS MY RENDER NOT WORKING???
        res.render('templates/' + mongooseResult.coreFit,  Object.assign({}, WP.get_WP_data(resultsPage), getPartials(mongooseResult.modules), analyticsData), (err, html) => {if (err) console.log(err); else res.send(html);});
      } else {
        throw new Error('GETTING PAGE DATA RETURNED UNDEFINED');
      }
    };

传入请求首先路由到/submit POST路由 - 它操纵一些数据,将其全部存储在数据库中,然后res.redirect()/results?id=12345 GET路由,后者运行上面的逻辑。

render()实际发射的是什么时髦!回调((err, html) => {if (err) console.log(err); else res.send(html);})将呈现的HTML发送到如果您在第二时间点击路线。

完成调查不会产生回复;但它成功地将所有信息存储在DB和console.logs中,客户端请求应该重定向到的ID。用这个生成的ID / URL命中GET路由,通过复制粘贴它,渲染就好了。

交换简单res.send('wtf')的渲染工作 - 将实际响应发送到客户端。 (在本例中为字符串'wtf'...)

响应只是不发回数据。我不明白。有什么想法吗?

更新 奇怪的是,手动点击路线与我之前的POST请求中的重定向相比,使用简单的res.send('wtf mate')产生不同的结果。

点击GET路线并手动将先前存在的ID传递给req.query: enter image description here

在之前的POST请求res.redirect()来电之后点击GET路线: enter image description here

这可能更像Express请求类型不匹配问题?为什么res.redirect('/results?id=someString')调用会改变URL而不是发回字符串/ HTML?

2 个答案:

答案 0 :(得分:2)

根据您的更新,听起来您的res.send()电话在客户端被奇怪地解释。 POST请求不应该影响URL栏,除非您特意告诉它 - 您是否检查过客户端最初发送此请求的位置?

我的猜测 - 因为您说上面发布的路由代码是在先前的POST路由上从res.redirect()命中的 - 是客户端逻辑期望response对象是URL字符串,并通过重定向首次点击GET路由,继承此响应对象。这样客户端就会尝试在URL栏中插入一大串HTML。

在这种情况下,手动点击GET路线,就像你说的那样,默认情况下只会从res.render()呈现HTML - 但是res.redirect()的初始点击可能不会。

答案 1 :(得分:1)

让我们尝试通过测试代码部分调试问题。

我有一些线索,其中一条就是'templates/' + result.coreFit没有模板。
如果coreFit文件夹中的文件具有相同的值名称,请尝试检查templates值。

试试这段代码并告诉我它是否有效:

const 
  _ = require('lodash'),
  mongoose = require('mongoose');

const getQuizResultById = quizId => {
    return new Promise((resolve, reject) => {
        const 
            Result = mongoose.model('Result'),
            query = {
                quizId
            };

        Result
            .findOne(query)
            .then(resolve)
            .catch(reject);
    });
};

const getPageData = result => {
    if (_.get(result, 'answers.section1.question1.answer')) {
        let resultsPage = WP.getPage(wp_pages_data, 'slug', result.coreFit);
        let 
        analyticsData = _.pick(result, ['quizId', 'coreFit', 'secondFit', 'views']);
        analyticsData.degree = _.get(result, 'answers.section1.question1.answer');
        analyticsData.year = _.get(result, 'answers.section1.question2.answer');        
        analyticsData.concentration = _.get(result, 'answers.section1.question3.answer');

        result.views++;
        result.save();

        return [resultsPage, analyticsData, result];
    }

    throw new Error('S1Q1 IS UNDEFINED');
}

const renderPage = ([resultsPage, analyticsData, result], res) => {
    if (resultsPage) {
        return res.render(
            'templates/' + result.coreFit,  
            Object.assign({}, WP.get_WP_data(resultsPage), getPartials(result.modules), analyticsData), 
            (err, html) => {
                if (err) {
                    console.log(err);
                    return res.status(500).send('Ooopsss...');
                }
                res.send(html);
            });
    } 

    throw new Error('GETTING PAGE DATA RETURNED UNDEFINED');
};

router.get('/results', (req, res) => {
    getQuizResultById(req.query.id)
        .then(getPageData)
        .then(data => {
           renderPage(data, res);
        })
        .catch(errorHandler);
});