Promise.then不是一个函数 - 在React中处理多个API调用

cra*_*eld 4 javascript promise reactjs react-select

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

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

这个关于多个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}
    })
}
Run Code Online (Sandbox Code Playgroud)

Ber*_*rgi 7

您的问题是getAsync并不总是返回承诺,因此您无法链接.then(…)到每个呼叫.如果没有输入,则返回一个普通对象 - 而是需要返回使用该对象解析的promise:

if (!input) {
   return Promise.resolve({ options: [] });
}
Run Code Online (Sandbox Code Playgroud)


cra*_*eld 1

所以事实证明 if 语句导致了错误:

if (!input) {
  return {options: []}
}
Run Code Online (Sandbox Code Playgroud)

但我不知道为什么会这样。如果有人能解释原因,那么对于未来的问题来说,这将是一件好事。

这是我遵循@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}
    })
}
Run Code Online (Sandbox Code Playgroud)