【问题标题】:Cannot set headers after they are sent to the client error (Node/Express noob, other solutions didn't seem to work or didn't understand them))将标头发送到客户端后无法设置标头错误(Node/Express noob,其他解决方案似乎不起作用或不理解它们)
【发布时间】:2021-07-31 21:39:02
【问题描述】:

我查看了其他有类似问题的人的答案,但我对这一切仍然有点陌生,所以也许我没有正确理解或实施类似问题的解决方案。

这是我正在尝试练习的 Node/Express 应用程序,我使用 API 从搜索字段中获取经度和纬度,然后使用该 API 响应数据来使用另一个使用经度和纬度的 API获取天气数据。我有另一个应用程序,我在其中静态编码纬度和经度,一切正常。但是,我确实有嵌套的 API 调用,以及新的发布请求。

当我尝试渲染视图时,我收到了这个错误,“错误 [ERR_HTTP_HEADERS_SENT]:无法在将标头发送到客户端后设置标头”。当我测试并删除第二个嵌套 API 调用时,它可以工作,或者如果我取出第二个 res.render,它似乎可以工作。

我不知道我正在做的事情是不可能的,还是像我说的那样,人们遇到过类似的问题,我只是没有正确实施任何解决方案。

理想情况下,我需要从嵌套 API 调用“weatherDataResponse”中获取数据到 res.render 视图。 我确实让它自己工作,但是当我引入 /post 和顶级 API 调用时,它不起作用。

代码:

function latLongInfo(results) {
  let obj = {
    method: 'GET',
    url: 'https://forward-reverse-geocoding.p.rapidapi.com/v1/forward',
    params: {
      street: '',
      city: results.city,
      state: results.state,
      postalcode: results.zip,
      country: 'USA',
      'accept-language': 'en',
      polygon_threshold: '0.0'
    },
    headers: {
      'x-rapidapi-key': rapidApiKey,
      'x-rapidapi-host': 'forward-reverse-geocoding.p.rapidapi.com'
    }
  }
  return obj
};

app.get('/', function(req, res) {
  res.render('index', { title: 'idk' });
});

app.post('/getweather', (req, res, next) => {
    const cityWeatherSearch = req.body.cityWeatherSearch
    next();
    axios.request(latLongInfo(parseLatLongSearch(cityWeatherSearch)))
    .then(function (response) {
      const getLatLongInfoResponse = response.data[0]
      console.log(getLatLongInfoResponse)
      if (Object.keys(getLatLongInfoResponse).length < 1) {
      
        res.render('invalidweather', { title: 'Invalid Results' });
      }
      else {
        let lat = getLatLongInfoResponse.lat, lon = getLatLongInfoResponse.lon;
        let latLonString = `${lat},${lon}`;
        const getWeatherInfo = axios.get(`https://api.pirateweather.net/forecast/${pirateWeatherKey}/${latLonString}`)
        axios.all([getWeatherInfo]).then(axios.spread((...responses) => {
          const weatherDataResponse = responses[0].data;
          console.log(weatherDataResponse)
          res.render('weather', { title: 'Weather Results' });
        })).catch(errors => {
          console.error(errors);
        })
      }
    })
    .catch(function (error) {
      console.log(error)
    })  
    res.end()

    
  })

【问题讨论】:

  • 如果你在响应请求,为什么还要调用 next()?听起来可能是问题所在。
  • @AlexisTyler,哦,那没有任何区别。我删除并尝试将 next() 放在一些地方,我认为他们应该从阅读其他问题的回复中去。
  • next() 仅在该请求处理程序未处理请求并且您想要转到下一个处理程序时才需要调用。对于标准请求,您不需要调用它。
  • @AlexisTyler 谢谢你提供的信息,我不是 100% 知道它做了什么,所以我肯定是用错了!

标签: javascript node.js express


【解决方案1】:

试试这样的。看起来next() 调用导致了这里的问题。我还稍微重构了异步内容,使其更具可读性。

function latLongInfo(results) {
  let obj = {
    method: 'GET',
    url: 'https://forward-reverse-geocoding.p.rapidapi.com/v1/forward',
    params: {
      street: '',
      city: results.city,
      state: results.state,
      postalcode: results.zip,
      country: 'USA',
      'accept-language': 'en',
      polygon_threshold: '0.0'
    },
    headers: {
      'x-rapidapi-key': rapidApiKey,
      'x-rapidapi-host': 'forward-reverse-geocoding.p.rapidapi.com'
    }
  }
  return obj
};

app.get('/', function(req, res) {
  res.render('index', { title: 'idk' });
});

app.post('/getweather', async (req, res, next) => {
    try {
        const cityWeatherSearch = req.body.cityWeatherSearch;
        const response = await axios.request(latLongInfo(parseLatLongSearch(cityWeatherSearch)));
        const getLatLongInfoResponse = response.data[0]
        console.log(getLatLongInfoResponse)

        if (Object.keys(getLatLongInfoResponse).length < 1) {
            res.render('invalidweather', { title: 'Invalid Results' });
            return;
        }

        const lat = getLatLongInfoResponse.lat;
        const lon = getLatLongInfoResponse.lon;
        const latLonString = `${lat},${lon}`;
        const getWeatherInfo = await axios.get(`https://api.pirateweather.net/forecast/${pirateWeatherKey}/${latLonString}`);
        const weatherDataResponse = getWeatherInfo.data;
        console.log(weatherDataResponse)
        res.render('weather', { title: 'Weather Results' });
    } catch (error) {
        console.log(error);
    }
});

【讨论】:

  • 它看起来有效。我可以发誓我在没有 next() 的情况下也试过了。虽然,我没有尝试异步 app.post,但我不确定 app.post 是否可以接受。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-28
  • 1970-01-01
  • 2021-10-24
  • 2019-12-25
  • 2022-11-30
  • 1970-01-01
相关资源
最近更新 更多