ExpressJS очевидное состояние гонки между Promise и EventEmitter

У меня есть веб-приложение NodeJS/Express, которое позволяет пользователю загружать файл, который я затем анализирую, используя connect-busboy, сохранить в моей базе данных, используя Sequelize. Как только это будет сделано, я хочу перенаправить пользователя на данную страницу. Но Экспресс возвращает статус 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');
       });
   });
}

Я могу подтвердить, что мои данные сохраняются правильно. Но из-за состояния гонки на веб-странице написано "не могу POST" из-за статуса 404, возвращаемого Express, и res.redirect не удается с ошибкой установки заголовков, потому что он пытается перенаправить после отправки 404.

Может кто-нибудь помочь мне понять, почему Экспресс возвращает 404?

1 ответ

Решение

Проблема связана с вашим внутренним вызовом к busboy внутри вашего обработчика. Вместо того, чтобы выполнять и просто возвращать управление вашему обработчику, он будет вызывать next который передается ему, прежде чем он вернет контроль. Таким образом, вы выполняете код после вызова busboy, но запрос уже продвинулся дальше этой точки.

В тех случаях, когда вы хотите, чтобы некоторое промежуточное программное обеспечение выполнялось только для определенных запросов, вы можете связать промежуточное программное обеспечение с этими запросами, такими как:

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

Вы также можете разделить их с .use() такие как:

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

Все вышеперечисленное объединит промежуточное программное обеспечение так, как вы хотели. В случае .use() промежуточное программное обеспечение также будет применяться к любым применимым .METHOD() как Экспресс ссылается на это в своей документации.

Также обратите внимание, что таким способом вы можете передавать произвольное количество промежуточного программного обеспечения либо в виде отдельных параметров, либо в виде массивов функций промежуточного программного обеспечения, таких как:

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

Поведение при выполнении любого из приведенных выше примеров будет эквивалентным. Говоря только для себя и не предполагая, что это лучшая практика, я обычно использую дополнение промежуточного программного обеспечения на основе массива, только если создаю список промежуточного программного обеспечения во время выполнения.

Удачи с этим. Надеюсь, вам нравится пользоваться Express так же, как и я.

Другие вопросы по тегам