具有嵌套承诺的可选承诺的问题

时间:2018-02-12 17:27:51

标签: javascript node.js

我有一个服务器GET请求,我试图从一个函数创建一个承诺,但它不太顺利。我需要这个承诺是可选的,如果可能的话,那么如果结果是空的,那么它应该被忽略(我已经标记了它不应该继续使用带有IGNORE FUNCTION字样的函数)。

这个想法是它遍历docs内的snapshot,并将它们添加到数组调用jamDocs。然后,如果该数组不为空,则应遍历每个阻塞并为每个数据调用异步函数。然后设置卡纸hostName。完成后,原始承诺应返回jamDocs

如果jamDocs为空,则应忽略整个承诺。最后,在完成其他promise(有一个名为profilePromise的返回配置文件对象)之后,应将jams分配给配置文件对象,并将对象以200状态代码发送回客户端。

我的代码:

var jamsQuery = firebase.db.collection('users')
                  .where("hostId", "==", id)
                  .orderBy("createdAt")
                  .limit(3)
var jamsPromise = jamsQuery.get().then(snapshot => {
  var jamDocs = []
  snapshot.forEach(doc => {
    var jam = doc.data()
    jam.id = doc.id
    jamDocs.push(jam)
  })
  if (!snapshot.length) { // Error: Each then() should return a value or throw
    return // IGNORE FUNCTION
  } else {
    var jamNamePromises = jamDocs.map(function(jam) {
      var jamRef = firebase.db.collection('users').doc(jam.hostId)
      return jamRef.get().then(doc => {
        if (doc.exists) {
          jam.hostName = doc.data().firstName
          return jam
        } else {
          throw new Error("yeah")
        }
      })
    })
    Promise.all(jamNamePromises)
      .then(function() {
        return jamDocs
      })
      .catch(...)
  }
})

// Later on
Promise.all(profilePromise, jamsPromise)
.then(objectArray => {
  var profile = objectArray[0]

  myProfile.jams = jamDocs
  return res.status(200).send(myProfile);
})
.catch(
  res.status(500).send("Could not retrieve profile.")
)

我收到如下错误:Each then() should return a value or throwAvoid nesting promises。我该如何解决?谢谢!

2 个答案:

答案 0 :(得分:0)

此行上的then并未返回任何内容,并且还包含嵌套的承诺。 var jamsPromise = jamsQuery.get().then(snapshot => {

你应该重构它,然后在这之外移动嵌套的promises:

var jamsPromise = jamsQuery.get()
    .then(snapshot => {
        var jamDocs = []
        snapshot.forEach(doc => {
            var jam = doc.data()
            jam.id = doc.id
            jamDocs.push(jam)
        })
        if (!snapshot.length) {
            return // IGNORE FUNCTION
        } else {
        var jamNamePromises = getJamDocsPromises();

        return Promise.all(jamNamePromises);
    })
    .catch(...)
});

function getJamDocsPromises(jamDocs) {
    return jamDocs.map(function(jam) {
        var jamRef = firebase.db.collection('users').doc(jam.hostId)
        return jamRef.get().then(doc => {
           if (doc.exists) {
               jam.hostName = doc.data().firstName
               return jam
           } else {
               throw new Error("yeah")
           }
    });
}

答案 1 :(得分:0)

  

如果结果为空,则应忽略(不应继续使用该功能)。如果该数组不为空,则应该遍历每个阻塞

不要让它变得比它需要的更复杂。无论如何,循环一个空集合什么都不做,所以你不需要特殊情况。只需继续使用空数组。

var jamsPromise = jamsQuery.get().then(snapshot => {
  var jamDocs = []
  snapshot.forEach(doc => {
    jamDocs.push(Object.assign(doc.data(), {id: doc.id}))
  })
  return Promise.all(jamDocs.map(function(jam) {
    return firebase.db.collection('users').doc(jam.hostId).get().then(doc => {
      if (doc.exists) {
        jam.hostName = doc.data().firstName
        return jam
      } else {
        throw new Error("yeah")
      }
    })
  }))
})
  

我得到的错误如下:每个then()应返回一个值或抛出

您忘记了return前面的Promise.all

  

避免嵌套承诺。我该如何解决这个问题?

nothing wrong with nesting promises,但在您的情况下,.then(() => jamDocs)不是必需的,因为Promise.all已经解析了内部承诺所满足的所有jam的数组