在中间件日志之间正确传递数据但 returns 在对象内部未定义
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.invoice这样的路径是我的第一个中间件。
req.invoicePath = path.resolve(dest + fileName);
有关如何使用 mailgun 发送电子邮件的简要说明,请参见 mailgun blog here
非常感谢任何帮助,谢谢!
您有异步计时问题。在您的第一个中间件中,您在 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
,你没有任何处理程序来做一些智能的事情。
我所做的更改:
- 将
next()
移动到 Invoice.find()
回调内部,因此在设置 req.invoicePath
之前不会调用它。
- 在
generateInvoice()
函数中移动了 fileName, dest, invoiceNr
的变量声明,因此它们对于函数的每次调用都是唯一的,并且同时进行中的其他请求不会破坏它们的值。
其他潜在问题:
- 您声明
generate()
接受一个错误参数,但您没有将参数传递给它。
generate()
中的 throw err
如果被击中,将不会被捕获并做任何有用的事情。
- 您在构建 PDF 文档时没有任何错误处理。
- 如果 PDF 文件的任何构造是异步的,则在让下一个中间件尝试使用它之前您不会等待它完成,因此可能存在尚未完成写入的竞争条件在您尝试使用它之前。
我在两个快速中间件之间传递数据,因为我的一个变量设置在函数(中间件 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.invoice这样的路径是我的第一个中间件。
req.invoicePath = path.resolve(dest + fileName);
有关如何使用 mailgun 发送电子邮件的简要说明,请参见 mailgun blog here 非常感谢任何帮助,谢谢!
您有异步计时问题。在您的第一个中间件中,您在 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
,你没有任何处理程序来做一些智能的事情。
我所做的更改:
- 将
next()
移动到Invoice.find()
回调内部,因此在设置req.invoicePath
之前不会调用它。 - 在
generateInvoice()
函数中移动了fileName, dest, invoiceNr
的变量声明,因此它们对于函数的每次调用都是唯一的,并且同时进行中的其他请求不会破坏它们的值。
其他潜在问题:
- 您声明
generate()
接受一个错误参数,但您没有将参数传递给它。 generate()
中的throw err
如果被击中,将不会被捕获并做任何有用的事情。- 您在构建 PDF 文档时没有任何错误处理。
- 如果 PDF 文件的任何构造是异步的,则在让下一个中间件尝试使用它之前您不会等待它完成,因此可能存在尚未完成写入的竞争条件在您尝试使用它之前。