Как правильно выйти из функции второго уровня, используя next в nodeJS express? - PullRequest
1 голос
/ 12 февраля 2020

Ниже приведен мой стилизованный код:

let the_function = (req, res, next) => {
    Promise
        .map(promises_params, (x) => {
                return get_promise(x);
            }, {concurrency: 20}
        ).then((values) => {

        let reduceFunc = (acc, currV, currI) => {
            if (something_bad) {
                next(new Error("something bad happened");
                return;
            } else {
                return acc;    
            }
        };
        let result = values.reduce(reduceFunc,[]);
        res.send(result);
    }).catch((err) => {
        res.send(err);
    });
};

Идея состоит в том, что я выполняю кучу обещаний, а затем уменьшаю значения, которые получаю, до одного объекта, который затем отправляю обратно пользователю.

Когда something_bad происходит в пределах функции уменьшения reduceFunc, я хотел бы получить надлежащую ошибку, отправленную обратно пользователю. Но в моей текущей настройке сервер node.js не работает и должен перезагрузиться после того, как я получу:

_http_outgoing.js:494
    throw new ERR_HTTP_HEADERS_SENT('set');
    ^

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

, и пользователь получит ошибку, которая не та, которую я хотел бы, чтобы она увидела.

Как убедиться, что ошибка, которую я хочу видеть пользователю, выводится чисто, не убивая при этом сервер?

1 Ответ

1 голос
/ 12 февраля 2020

Причиной возникновения ошибки является то, что вызов next не останавливает выполнение функции Reduce. Функция сокращения продолжает работать и в итоге вызывается res.send(results). Это становится проблемой, потому что следующий обработчик маршрута, очевидно, также отправляет ответ, но только один ответ может быть отправлен на запрос, поэтому вы получаете сообщение об ошибке.

Тот факт, что вы не вызываете next в вашем Обработчик catch указывает, что вы не хотите использовать next. Так как это так, вы можете просто throw сообщить об ошибке, так что выполнение функции Reduce будет прервано и обработчик catch вызывается.

let the_function = (req, res, next) => {
    Promise
        .map(promises_params, (x) => {
                return get_promise(x);
            }, {concurrency: 20}
        ).then((values) => {

        let reduceFunc = (acc, currV, currI) => {
            if (something_bad) {
                throw new Error("something bad happened");
            } else {
                return acc;    
            }
        };
        let result = values.reduce(reduceFunc,[]);
        res.send(result);
    }).catch((err) => {
        res.send(err);
    });
};

Теперь ответ отправляется только один раз. Он отправляется, если функция сокращения завершается без something_bad, или когда происходит ошибка, но никогда вместе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...