【问题标题】:Promise.then is not a function - handling multiple API calls in ReactPromise.then 不是一个函数 - 在 React 中处理多个 API 调用
【发布时间】:2017-10-10 13:13:40
【问题描述】:

我正在使用react-select 来自动完成搜索栏中的选项。搜索栏会显示两个类别之一的结果,具体取决于它所访问的 API 端点。

现在,它可以处理来自一个点或另一个点的数据,但我无法将来自两个端点的数据返回到 react-select 的 loadOptions 参数。

来自this answer关于多个API调用,我决定使用promises一次返回所有数据,但我收到错误Uncaught TypeError: promise.then is not a function at Async.loadOptions

这是我的loadOptions 代码:

const getAsync = (tripId, destinationIndex, input) => {
  if (!input) {
    return { options: [] }
  }

  function getMusement(input) {
    return new Promise(function(resolve, reject) {
      TVApi.musement.autocomplete(input)
        .then((m) => {
          const musementOptions = m.map(musementToOption).slice(0, 4)
          return resolve(musementOptions)
        })
    })
  }

  function getFourSquare(tripId, destinationIndex, input) {
    return new Promise(function(resolve, reject) {
      TVApi.spot.autocomplete(tripId, destinationIndex, input)
        .then((fs) => {
          const fsOptions = fs.map(spotToOption).slice(0, 4)
          return resolve(fsOptions)
        })
    })
  }

  return Promise.all([getMusement(input), getFourSquare(tripId, destinationIndex, input)])
    .then((allData) => {
      const merged = [].concat.apply([], allData)
      console.log(JSON.stringify(merged)) // logs out with correct data
      return {options: merged}
    })
}

【问题讨论】:

  • TVApi.musement.autocomplete 是否返回承诺?
  • 具体在哪一行?你确定TVApi 方法总是返回承诺吗?
  • @Bergi 没有它我该怎么做?
  • @crashspringfield 你只需要写function getMusement(input) { return TVApi.musement.autocomplete(input).then(m => { … return musementOptions }) }getFourSquare 也一样)

标签: javascript reactjs promise react-select


【解决方案1】:

您的问题是 getAsync 并不总是返回承诺,因此您不能将 .then(…) 链接到每个调用。当没有输入时,您返回的是一个普通对象 - 相反,您需要返回一个使用该对象解析的承诺:

if (!input) {
   return Promise.resolve({ options: [] });
}

【讨论】:

  • 由于某种原因这不起作用,但它可能与 react-select 库有关。 if 语句现在只是让搜索栏放弃。当它只进行一次 API 调用(使用回调)时,搜索栏总是会响应新的输入。现在它没有响应。
  • 我之前以为它会抛出错误?现在至少它不会那样做 :-) 不确定你如何使用它,以及为什么解决承诺会阻止它进一步搜索,但你应该用选择代码询问一个关于这个问题的单独问题。
【解决方案2】:

原来是 if 语句导致了错误:

if (!input) {
  return {options: []}
}

但我不知道为什么会这样。如果有人可以解释原因,那将是很好的了解未来的问题。

这是我按照@Bergi 的建议避免Promise Constructor antipattern 得到的解决方案

const loadOptions = (tripId, destinationIndex, input) => {

  function getMusement(input) {
    return TVApi.musement.autocomplete(input)
      .then((m) => {
        const musementOptions = m.map(musementToOption).slice(0, 3)
        return musementOptions
      })
  }

  function getFourSquare(tripId, destinationIndex, input) {
    return TVApi.spot.autocomplete(tripId, destinationIndex, input)
      .then((fs) => {
        const fsOptions = fs.map(fsToOption).slice(0, 2)
        return fsOptions
      })
  }

  return Promise.all([getMusement(input), getFourSquare(tripId, destinationIndex, input)])
    .then((allData) => {
      const merged = [].concat.apply([], allData)
      return {options: merged}
    })
}

【讨论】:

  • 感谢您的提示,请参阅我的答案以了解为什么会出现问题以及如何解决它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-27
相关资源
最近更新 更多