簡體   English   中英

在中間件日志之間正確傳遞數據,但在對象內部返回未定義

[英]Passing data between middleware logs correctly but returns undefined inside object

我正在兩個表達中間件之間傳遞數據,因為我的變量之一是在函數(中間件1)中設置的,需要在其功能范圍之外(在中間件2中)進行訪問。 當我在第二個中間件中使用console.log req.invoice時,它會正確記錄日志,因此我知道我已正確地在中間件之間傳遞了數據,但是當嘗試使用變量在第二個中間件中構造新對象時,req.invoice是未定義。

var express = require('express');
var app = express();
var Invoice = require('../models/Invoice');
var router = express.Router();
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var expressValidator = require('express-validator');
var fs = require('fs');
//Used to create a pdf invoice
var PDFDocument = require('pdfkit');

//Route
router.route('/:item')
  .post(generateInvoice, sendMail, function(req, res){

  });

//First middleware

var fileName, dest, invoiceNr;
function generateInvoice (req, res, next) {
  //Destination for storing the invoice file
  dest = __dirname + '/../static/';
  //generate invoice nr
   Invoice.find(function(err, invoices){
    if(err) {
     return res.send(err);
    } else {
      invoiceNr = invoices.length + 1;
      fileName = 'invoice' + invoiceNr + '.pdf';
      req.invoicePath = path.resolve(dest + fileName);
      generate();
    }
  });
  //Create the invoice and store in static directory 
  function write() {
    doc = new PDFDocument();
    doc.pipe(fs.createWriteStream(dest + fileName));
    doc.text(invoice, 100, 100);
    console.log('File written > ' + fileName + '\n Destination: ' + dest);
    doc.end();
  }
  function generate (err){
    if (err)
      throw err;
    if (invoiceNr !== undefined) {
      write();
    }
  }

  next();

}

//Second middleware
//I'm using mailgun-js to send the invoice via email
function sendMail(req, res, next){
  //Mailgun implementation
  var api_key = 'MY_KEY';
  var domain = 'MY_DOMAIN';
  var mailgun = require('mailgun-js')({apiKey: api_key, domain: domain});
  var data = {
    from: 'APP_MAIL',
    to: 'example@mail.com',
    subject: 'Hello',
    text: 'Should include attachment!',
    //req.invoicePath is undefined when it should be a filepath
    attachment: req.invoicePath
    //when invoicePath was set as a static string, the attachment was included in the email
    //attachment: '/Users/anton/Desktop/app/src/server/static/invoice27.pdf'
  };

  //again I'm using mailgun-js for sending the emails
  mailgun.messages().send(data, function (error, body) {
    console.log('Message body: ' + body);
    //This works and I get the above: '/Users/anton/Desktop...' in the console
    console.log('The path to the invoice: ' + req.invoicePath);
    //Works properly as well
    console.log('The path is of type: ' + typeof(req.invoicePath));
  });
  res.end();
}

我已經將req.invoicePath設置為這是我的第一個中間件。

req.invoicePath = path.resolve(dest + fileName);

可以在mailgun博客上找到有關如何使用mailgun發送電子郵件的簡要說明,非常感謝任何幫助,謝謝!

您有異步計時問題。 在您的第一個中間件中,您要在Invoice.find()函數完成之前調用next() ,從而在設置req.invoicePath之前執行第二個中間件。

要解決此問題,僅在完成第一個中間件中的異步操作后才調用next() 您還需要將變量移到generateInvoice()內,以便它們是受保護的局部變量,並且不會被同時在運行的另一個請求所截斷:

function generateInvoice (req, res, next) {
  var fileName, dest, invoiceNr;
  //Destination for storing the invoice file
  dest = __dirname + '/../static/';
  //generate invoice nr
   Invoice.find(function(err, invoices){
    if(err) {
     return res.send(err);
    } else {
      invoiceNr = invoices.length + 1;
      fileName = 'invoice' + invoiceNr + '.pdf';
      req.invoicePath = path.resolve(dest + fileName);
      generate();
      // move next() here so it is not called until after req.invoicePath is set
      next();
    }
  });
  //Create the invoice and store in static directory 
  function write() {
    var doc = new PDFDocument();
    doc.pipe(fs.createWriteStream(dest + fileName));
    doc.text(invoice, 100, 100);
    console.log('File written > ' + fileName + '\n Destination: ' + dest);
    doc.end();
  }
  function generate (err){
    if (err)
      throw err;
    if (invoiceNr !== undefined) {
      write();
    }
  }
}

由於我假設write()可能包含一些異步部分,因此這里也可能存在其他異步問題。 並且,您顯示了一個generate()參數,但沒有傳遞參數。 而且,如果generate()執行了throw err ,那么您將沒有任何處理程序來執行某些智能操作。

我所做的更改:

  1. next()移動到Invoice.find()回調內部,以便在設置req.invoicePath之后才調用它。
  2. generateInvoice()函數中為fileName, dest, invoiceNr移動的變量聲明,因此對於函數的每次調用它們都是唯一的,並且同時進行中的其他請求不會刪除其值。

其他潛在問題:

  1. 您聲明了generate()接受一個err參數,但沒有將其傳遞給它。
  2. 如果被擊中, generate()throw err不會被捕獲並且做任何有用的事情。
  3. 您對PDF文檔的構建沒有任何錯誤處理。
  4. 如果PDF文件的任何構造都是異步的,則在等待下一個中間件嘗試使用它之前,您不必等待它完成,因此在嘗試之前可能存在尚未完成編寫的競爭狀況使用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM