2016-07-09 69 views
0

我2個明示中間件之間傳遞數據如被設定在函數(中間件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: '[email protected]', 
    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 blog here 發現在所有的任何幫助非常感謝,謝謝!

+0

哪裏是第一中間件和第二中間件?你的'sendMail()'函數沒有輸出,也沒有修改任何東西,所以我們不確定它應該做什麼?請顯示第一個中間件和第二個中間件的實際代碼。 – jfriend00

+0

好的,我會確保編輯我的問題,以便更容易地遵循。 –

回答

0

您有異步計時問題。在你的第一個中間件中,你打電話next()之前你的Invoice.find()功能已經完成,從而執行第二個中間件,然後再設置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. fileName, dest, invoiceNrgenerateInvoice()函數內部移動變量聲明所以它們對於功能,並在同一時間將不打敗它們的值在飛行中的其他請求的每次調用唯一的。

其他潛在的問題:

  1. 你宣佈generate()接受一個犯錯的參數,但你沒有通過一個給它。
  2. throw errgenerate()不會被抓住了,如果它是有史以來打做任何有用的。
  3. 您對PDF文檔的構造沒有任何錯誤處理。
  4. 如果任何PDF文件的建設是異步的,你是不是在等待它在你面前,讓接下來的中間件嘗試使用它,有可能是在那裏還沒有完成寫入的競爭條件尚未完成前正在嘗試使用它。
+0

謝謝你一個很好的解釋和徹底的答案!這現在解決了我的問題。顯然,我需要學習很多東西來使代碼更可靠。我已經清理了更多的代碼,並移除了generate()函數,現在立即調用write()函數,以便更容易跟蹤。然而,我的sendMail()函數執行,但現在沒有電子郵件正在發送只有日誌正在發生。當然,我會接受你的回答,因爲它解決了我的問題,我一定會想出另一件事。乾杯! –