【问题标题】:Successive promise calls overriding return value连续的承诺调用覆盖返回值
【发布时间】:2019-09-28 18:15:41
【问题描述】:

我有一个 React 站点,我设置了一个组件来显示当前温度以及 10 和 20 年前的当前温度。 (我使用的是DarkSky。)

组件看起来像这样(简化):

class WeatherPreview extends React.Component {
  state = {
    weather: {},
    weatherTen: {},
    weatherTwenty: {}
  }

  getWeather = async (years) => {
    const targetDate = years ? moment().subtract(years, 'years') : null

    const basePath = 'http://localhost:3000'

    const res = targetDate ?
      await fetch(`${basePath}/api/weather?date=${targetDate}`) :
      await fetch(`${basePath}/api/weather`)

    const weather = await res.json()

    return weather
  }

  async componentDidMount() {
    const weather = await this.getWeather()
    const weatherTen = await this.getWeather(10)
    const weatherTwenty = await this.getWeather(20)

    this.setState({ weather, weatherTen, weatherTwenty })
  }

  render() {
    const { weather, weatherTen, weatherTwenty } = this.state

    return (
      <div>
        {weather.currently.temperature}°
        {weatherTen.currently.temperatureTen}°
        {weatherTwenty.currently.temperatureTwenty}°
      </div>
    )
  }
}

API 端点代码如下所示(简化):

const darkskyOptions = {
  latitude: 38.328732,
  longitude: -85.764771,
  language: 'en',
  units: 'us',
  exclude: ['minutely', 'hourly', 'daily', 'alerts', 'flags']
}

export default function handle(req, res) {
  const date = req.query.date || null

  if (!!date) {
    darkskyOptions.time = date
  }
  else {
    // Clear out time option if it's there
    // Or else it will mess up our current weather call
    delete darkskyOptions.time
  }

  const freshWeather = new Promise(resolve => resolve(
    darksky.options(darkskyOptions).get()
  ))

  freshWeather.then((newData) => {
    res.json(newData)
  }, (err) => {
    console.log('Error retrieving Dark Sky weather data.')
    console.log(err)
  })
}

当我在代码更改后刷新页面时,第一次加载正确的数据:

90° 75° 72°

但是,当我在此初始加载后刷新页面时,过去 20 年的数据将替换当前数据。

72° 75° 72°

当我在 API 端点代码中记录内容时,从来没有任何东西会指示错误。 time 属性从不存在当前调用,它似乎总是被删除,正确的选项似乎总是被传递。从本质上讲,逻辑似乎已经过时了。

但如果我在组件中记录weatherweatherTwentyweather 肯定持有weatherTwenty 的值。

我的代码模式有问题吗?当那些 asnyc await 调用被调用时,它们是独一无二的,还是它们在返回时会“交叉”?

【问题讨论】:

    标签: javascript reactjs darksky


    【解决方案1】:

    问题可能是因为您正在改变选项并在请求之间继续使用它。请尝试以下操作:

    export default function handle(req, res) {
      const date = req.query.date || null
      //copy options and use that one
      const copyOptions = {...darkskyOptions};
    
      if (!!date) {
        copyOptions.time = date
      }
      else {
        // Clear out time option if it's there
        // Or else it will mess up our current weather call
        delete copyOptions.time
      }
    
      const freshWeather = new Promise(resolve => resolve(
        darksky.options(copyOptions).get()
      ))
    
      freshWeather.then((newData) => {
        res.json(newData)
      }, (err) => {
        console.log('Error retrieving Dark Sky weather data.')
        console.log(err)
      })
    }
    

    【讨论】:

    • 仍然得到相同的结果......非常奇怪
    • 我通过重新架构 API 路由为 Time Machine 调用使用不同的路由来修复它。但这并不能真正解释为什么会发生这种情况。
    • @DavidYeiser 什么是 darksy 对象,get 方法从何而来?
    • 嘿!再次查看那个包让我想到以null 打发时间,而不是仅仅从选项中删除它。以防它以某种方式持续存在于包装器中。我不确定它是否存在,但将其显式设置为 null 可以解决问题。
    • @DavidYeiser 看起来 darksky 对象保留了它以前的一些设置,但将其设置为 null 会覆盖它。很好,它现在可以工作了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-15
    • 2016-10-24
    • 1970-01-01
    • 2016-10-11
    • 2016-09-18
    • 1970-01-01
    相关资源
    最近更新 更多