Почему «return next ()» вызывает «Ошибка [ERR_HTTP_HEADERS_SENT]» - PullRequest
0 голосов
/ 24 октября 2019

Я создал чат-бот Dialogflow для конвертации валют. Я пишу свое собственное выполнение Dialogflow, которое вызывает API для ведения диалога по запросу пользователя. Я продолжаю получать сообщение об ошибке «Ошибка [ERR_HTTP_HEADERS_SENT]» с «возвратом следующего ()» в моем коде. Как только он закомментирован, мой код работает нормально.

Я продолжаю получать ошибку «Ошибка [ERR_HTTP_HEADERS_SENT]» с «return next ()» в моем коде. Как только он закомментирован, мой код работает нормально. Я хотел бы понять, почему. Введите код здесь

"use strict";

const express        = require("express"),
      request        = require("request"),
      app            = express()

app.use(express.json())

// POST route handler
app.post("/", (req, res, next) => {
  let { queryResult } = req.body;
  if (queryResult) {
    const { outputCurrency, amountToConvert } = queryResult.parameters;
    // Check if input currency code === output currency code
    if (amountToConvert.currency === outputCurrency) {
      const { amount } = amountToConvert;
      let responseText = `Well, ${amount} ${outputCurrency} is obviously equal to ${amount} ${outputCurrency}!`;
      let respObj = {
        fulfillmentText: responseText
      };
      res.json(respObj); //send back object to Dialogflow
    } else {
      // Query the currencyconverter API to fetch rates and create a response
      convertCurrency(amountToConvert, outputCurrency, (error, result) => {
        if (!error && result) {
          let respObj = {
            fulfillmentText: result  //send back response to Dialogflow
          };
          res.json(respObj);          
        }
      });
    }
  }
  //return next();   //with this line running, I keep getting 
                    //Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
});

//function to call API and convert currency
const convertCurrency = (amountToConvert, outputCurrency, cb) => {
    const { amount, currency } = amountToConvert;
    const reqObj = //assemble the api request
    { 
      url: "https://free.currconv.com/api/v7/convert",
      qs: {        
        q: `${currency}_${outputCurrency}`,
        compact: "ultra",
        apiKey: "f0a68e5b725035985796"
      },
      method: "GET",
      json: true
    }
    return request( 
      reqObj,
      (error, response, body) => {   
        if (!error && response.statusCode === 200) {
          let computedValue = Math.round(
            body[`${currency}_${outputCurrency}`] * amount
          );
          cb( //this is the message i send back to Dialogflow (DF)
            null,
            `${amount} ${currency} converts to about ${outputCurrency} ${computedValue} as per current rates!`
          );
        } else {
          cb(error, null);
        }
      }
    );
  };

app.listen(3000, () =>{
  console.log("server started")
})

1 Ответ

1 голос
/ 24 октября 2019

В путях кода, куда вы отправляете ответ, вы также не хотите звонить next(). Ваш код делает это, и это приводит к тому, что какой-то другой маршрут вниз по линии также пытается отправить ответ, который приводит к сообщению «заголовки уже отправлены» внутри Express.

Вызов next() продолжит маршрутизациюна другие маршруты, и когда вы отправили ответ, вы не хотите этого делать. Ваш код должен отправить один и только один ответ для каждого возможного пути через обработчик маршрута. Кроме того, поскольку этот обработчик маршрута «обрабатывает» маршрут, нет никаких причин вызывать next() на любом пути через код. Вместо этого все возможные пути через код должны отправлять успешный ответ или ответ об ошибке и один-единственный ответ.

Вот одна попытка очистить все возможные пути в коде и добавить соответствующие ответы об ошибках:

// POST route handler
app.post("/", (req, res, next) => {
  let { queryResult } = req.body;
  if (!queryResult) {
    res.status(400).json({error: "Missing data in post"})
  } else {
    const { outputCurrency, amountToConvert } = queryResult.parameters;
    // Check if input currency code === output currency code
    if (amountToConvert.currency === outputCurrency) {
      const { amount } = amountToConvert;
      let responseText = `Well, ${amount} ${outputCurrency} is obviously equal to ${amount} ${outputCurrency}!`;
      res.json({fulfillmentText: responseText}); //send back object to Dialogflow
    } else {
      // Query the currencyconverter API to fetch rates and create a response
      convertCurrency(amountToConvert, outputCurrency, (error, result) => {
        if (error || !result) {
          console.log(error);
          res.status(500).json({error: "currency conversion failure"});
        } else  {
          res.json({fulfillmentText: result});   //send back response to Dialogflow
        }
      });
    }
  }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...