ExpressJS Promise和EventEmitter之间明显的竞争状态

我有一个NodeJS / Expressnetworking应用程序,允许用户上传文件,然后使用Sequelize使用connect-busboy保存到我的数据库。 一旦完成,我想将用户redirect到给定页面。 但是,在我的Promise解决之前,Express已经返回了404的状态,即使我从来没有调用next() ,为了调用中间件链中的下一个处理程序,我认为这是强制性的,从而导致了404。

这是我的代码到目前为止:

 function uploadFormFile(req, res, next) { var documentInstanceID = req.params.documentInstanceID; // set up an object to hold my data var data = { file: null, documentDate: null, mimeType: null }; // call the busboy middleware explicitly // EDIT: this turned out to be the problem... of course this calls next() // removing this line and moving it to an app.use() made everything work as expected busboy(req, res, next); req.pipe(req.busboy); req.busboy.on('file', function (fieldName, file, fileName, encoding, mimeType) { var fileData = []; data.mimeType = mimeType; file.on('data', function (chunk) { fileData.push(chunk); }); file.on('end', function () { data.file = Buffer.concat(fileData); }); }); req.busboy.on('finish', function () { // api methods return promises from Sequelize api.querySingle('DocumentInstance', ['Definition'], null, { DocumentInstanceID: documentInstanceID }) .then(function (documentInstance) { documentInstance.RawFileData = data.file; documentInstance.FileMimeType = data.mimeType; // chaining promise return api.save(documentInstance); }).then(function () { res.redirect('/app/page'); }); }); } 

我可以确认我的数据正在被正确保存。 但由于竞争条件,网页上说,由于Express返回404状态,“无法POST”,并且res.redirect失败,出现设置头的错误,因为它在404之后试图redirect发送。

谁能帮我弄清楚为什么快递正在返回404?

问题来自您的处理程序内部的busboy内部电话。 而不是它执行并简单地将控制权返回给你的处理程序,而是在它返回控制之前调用传递给它的next控制权。 所以你在busboy调用执行之后进行编码,但是请求已经超过了这个点。

在您希望某些中间件仅针对特定请求执行的情况下,可以将中间件链接到这些请求中,例如:

 router.post('/upload',busboy,uploadFromFile) 

你也可以用.use()分隔它们,例如:

 router.use('/upload', busboy); router.post('/upload', uploadFromFile); 

上述任何一种都会按照您的意图链接中间件。 在.use()的情况下,中间件也将被应用于任何适用的.METHOD()因为Express在其文档中提到它。

另外请注意,您可以以这种方式传递任意数量的中间件,可以作为单独的参数或中间件函数的数组,例如:

 router.post('/example', preflightCheck, logSomeStuff, theMainHandler); // or router.post('example', [ preflightCheck,logSomeStuff ], theMainHandler); 

以上任何一个例子的执行行为都是等价的。 只为自己说,而不是build议这是一个最佳做法,我通常只使用基于arrays的中间件添加,如果我在运行时构build中间件列表。

祝你好运。 我希望你尽可能喜欢使用Express。