7

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

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

这个关于多个 API 调用的答案中,我决定使用承诺一次返回所有数据,但我得到了错误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}
    })
}
4

2 回答 2

10

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

if (!input) {
   return Promise.resolve({ options: [] });
}
于 2017-05-11T14:40:33.277 回答
1

所以事实证明 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}
    })
}
于 2017-05-11T14:34:31.337 回答