Express. js - Невозможно установить заголовки с экспортированной функцией - PullRequest
0 голосов
/ 25 мая 2020

Изучение того, как проводить тестирование с помощью Express с использованием Mocha , Chai , Chai-HTTP plugin и MongoDB с Пн goose. У меня есть тест, который намеренно определяет, отправит ли MongoDB ошибку при попытке найти документ с ошибочным значением _id (слишком коротким).

Я заметил, что часть моего кода повторяется вокруг другого Express маршрутов и хочу повторно использовать его для других маршрутов, поэтому я экспортировал его из другого модуля, но теперь я получаю следующее:

Uncaught Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

Не уверен, почему я получаю эту ошибку . Если у меня тот же код, что и у экспортируемой функции, внутри кода маршрута он работает нормально, но при экспорте он просто жалуется.

Вот код:

test / route / example.test. js Snippit

it('Bad request with a too short ID string (12 characters minimum)', () => {
    // /api/v1/example is the endpoint
    // /blah is the param
    chai.request(app).get('/api/v1/example/blah').end((err, res) => {
       // Insert all the nice assert stuff. :) 
    });
});

route / example. js Snippit

// Packages
const router = require('express').Router();

// Models (Mongoose Schemas)
const Example = require('../models/example.model');

// Helpers
const { foundMongoError } = require('../helpers/routes');

// -----Snipped-----

router.route('/:exampleId').get((req, res) => {
    // Retrieve the exampleId parameter.
    const exampleId = req.params.exampleId;

    Example.findById(exampleId, (mongoError, mongoResponse) => {
        foundMongoError(mongoError, res); // Having an issue

        // If I have the same code that makes up foundMongoError inside here, no issues, 
        // but it will no longer be DRY.

        // Check if any responses from MongoDB
        if(mongoResponse) {
            res.status(200).json(mongoResponse);
        } else {
            return res.status(404).json({
                errorCode: 404,
                errorCodeMessage: 'Not Found',
                errorMessage: `Unable to find example with id: ${exampleId}.`
            });
        }
    });
});

helpers / routes. js

const foundMongoError = (mongoError, res) => {
    if(mongoError) {
        return res.status(400).json({
            errorCode: 400,
            errorCodeMessage: 'Bad Request',
            errorMessage: mongoError.message
        });
    }
};

module.exports = {
    foundMongoError
};

1 Ответ

2 голосов
/ 25 мая 2020

Это просто означает, что вы отправляете и отвечаете res дважды. В первый раз, когда вы отправляете его сюда:

    if(mongoError) {
        return res.status(400).json({
            errorCode: 400,
            errorCodeMessage: 'Bad Request',
            errorMessage: mongoError.message
        });
    }

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

    if(mongoResponse) {
        res.status(200).json(mongoResponse);
    } else {
        return res.status(404).json({
            errorCode: 404,
            errorCodeMessage: 'Not Found',
            errorMessage: `Unable to find example with id: ${exampleId}.`
        });
    }

Здесь происходит второй ответ, и здесь вы получаете ошибку.

Я бы переписал код следующим образом:

Вместо того, чтобы возвращать ответ, вы возвращаете true, что означает, что есть ошибка, иначе false:

const foundMongoError = (mongoError, res) => {
    if(mongoError) {
        res.status(400).json({
            errorCode: 400,
            errorCodeMessage: 'Bad Request',
            errorMessage: mongoError.message
        });
    return true;
    }
    return false;
};

module.exports = {
    foundMongoError
};

Тогда вы можете написать это так:

if(foundMongoError(mongoError, res)) return;

return остановит функцию для выполнения остальной части кода

...