在节点js中提交表单后无法加载CSS文件

时间:2017-12-04 12:41:43

标签: javascript css node.js

首先让我详细介绍一下。我使用节点的nodemailer从表单上提交的信息发送电子邮件。当我有一个收件人和一个html主体,它立即发送它,工作正常。但是当我将mailOptions2放在for循环中时,我就可以发送包含不同数组中的收件人和html主体的电子邮件。然后它仍然以不同的方式发送电子邮件和html内容。但是当提交表单时,在/send状态下它会继续加载,最终只加载页面的原始html,没有css。我收到这个错误:

Error: Can't set headers after they are sent.
    at validateHeader (_http_outgoing.js:489:11)
    at ServerResponse.setHeader (_http_outgoing.js:496:3)
    at ServerResponse.header (C:\Users\Ahmet Ömer\Desktop\Repairtechnician\node_modules\express\lib\response.js:767:10)
    at ServerResponse.send (C:\Users\Ahmet Ömer\Desktop\Repairtechnician\node_modules\express\lib\response.js:170:12)
    at done (C:\Users\Ahmet Ömer\Desktop\Repairtechnician\node_modules\express\lib\response.js:1004:10)
    at Immediate._onImmediate (C:\Users\Ahmet Ömer\Desktop\Repairtechnician\node_modules\express-handlebars\lib\utils.js:26:13)
    at runCallback (timers.js:781:20)
    at tryOnImmediate (timers.js:743:5)
    at processImmediate [as _immediateCallback] (timers.js:714:5)

我知道有关于此错误的帖子,但在我的情况下无法知道如何解决它,因为我还是初学者。

的NodeJS:

app2.engine('handlebars', exphbs2());
app2.set('view engine', 'handlebars');

// Static folder
app2.use('/public', express2.static(path2.join(__dirname, 'public')));
app2.use('/', express2.static(path2.join(__dirname, '')));

// Body Parser Middleware
app2.use(bodyParser2.urlencoded({ extended: false }));
app2.use(bodyParser2.json());

app2.get('/', (req, res) => {
  res.render('services');
});

app2.post('/send', (req, res) => {
  let mailList = ['xyz', 'xyz@gmail.com'];
  let outputs = [
    `
    <div>
    </div>  
  `,
  `
   <div>
   </div>  
`];

  // create reusable transporter object using the default SMTP transport
  let transporter2 = nodemailer2.createTransport({
    service: 'gmail',
    port: 25,
    secure: false,
    auth: {
        user: 'xyz@gmail.com', // senders email
        pass: 'xyz' // senders password
    },
    tls:{
      rejectUnauthorized:false
    }
  });

  for ( var i = 0; i < mailList.length; i++) {
      // setup email data with raw html
      let mailOptions2 = {
        from: '"xyz" <xyz@info.com>', // sender address
        to: mailList[i], // receiver or receivers
        subject: 'xyz', // Subject line
        html: outputs[i] // html body
    };

        // send mail with defined transport object
      transporter2.sendMail(mailOptions2, (error, info) => {
        if (error) {
            return console.log(error);
        }
        console.log('Message sent: %s', info.messageId);   
        console.log('Preview URL: %s', nodemailer2.getTestMessageUrl(info));

        res.render('services', {msg2:'xyz'});
    });
  }
});

正如我所说,如果我没有使用for mailOptions2循环将不同的值传递给指定区域,那么它就可以正常工作。

如果可能有帮助,这是我提到的文件的结构:

server.js
services.html
public
   css
      styles.css

1 个答案:

答案 0 :(得分:3)

您无法多次调用res.render(),因为res.render会将已编译的html发送给客户端。因此,只有在您希望向客户发送最终回复时,才需要致电res.render

对于这种情况,您可以使用Promise来管理sendMail回调:

// init this array outside the for loop
let sendMailPromises = [];

// this is inside the for loop
let promise = new Promise((resolve, reject) => {
    transporter2.sendMail(mailOptions2, (err, infos) => {
        if(err) reject(err)

        console.log('Mail sent %s', info.messageId);
        console.info('Preview URL: %s', nodeMailer2.getTest(info));
        resolve(infos)
    });

});
sendMailPromises.push(promise);

// this is after (and outside) the for loop.
Promise.all(sendMailPromises)
    .then(() => {
        res.render(mailOptions, {msg2: '...'})
    }).catch((err) => {
        console.error(err);
    })