javascript - ExpressJS Promise 和 EventEmitter 之间明显的竞争条件

标签 javascript node.js express promise busboy

我有一个 NodeJS/Express Web 应用程序,允许用户上传文件,然后我使用 connect-busboy 解析该文件。使用 Sequelize 保存到我的数据库。完成后,我想将用户重定向到给定页面。但在我的 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 失败并出现设置 header 错误,因为它在发送 404 后尝试重定向。

谁能帮我弄清楚为什么 Express 会返回 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);

上述任一示例的执行行为都是等效的。仅代表我自己,并不建议这是最佳实践,如果我在运行时构建中间件列表,我通常只使用基于数组的中间件添加。

祝你好运。我希望您和我一样喜欢使用 Express。

关于javascript - ExpressJS Promise 和 EventEmitter 之间明显的竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33025865/

相关文章:

javascript - 在 Mongoose 中过滤过滤结果

javascript - 如何将 Ember.js 与 Express.js 集成?

javascript - 无法让 JQuery 与 Express js 一起使用

javascript - href ="javascript:"在新选项卡中打开

javascript - 使用handlebars.js时创建新的 Bootstrap 行

node.js - Express 中 Mongoose 验证失败后如何向客户端返回错误消息

node.js - NodeJS 如何从 aws s3 存储桶将文件下载到磁盘?

node.js - 将 Node 版本从 v6.10 升级到 v10.x 后捆绑项目出现差异

javascript - Ampersand.js(或 Backbone.js)中的模型可以同时存在于多个集合中吗?

javascript - .然后链接不起作用。为什么?