Search code examples
node.jses6-promise

Avoid nesting promises


I'm getting an "Avoid nesting promises" (for jslint) for the following function. How can I write this without nesting promises?

function deleteUIDsFromDBForKey(rootkey, users_uids) {
  return retrieveUIDsFromDBForKey(rootkey)
    .then(uids => {
      let diff = uids.diff(users_uids)
      let deletes = []
      diff.forEach(key => {
        deletes.push(firebase.database().ref(rootkey + "/" + key).remove())
      })
      return Promise.all(deletes)
        .then(value => {
          return diff
        })
    })
}

Solution

  • The last then can be moved up to the main chain by returning the Promise.all result:

    function deleteUIDsFromDBForKey(rootkey, users_uids) {
      let diff;
      return retrieveUIDsFromDBForKey(rootkey)
        .then(uids => {
          diff = uids.diff(users_uids)
          let deletes = []
          diff.forEach(key => {
            deletes.push(firebase.database().ref(rootkey + "/" + key).remove())
          })
          return Promise.all(deletes)
        })
        .then(value => {
          return diff
        })
    }
    

    Note that for this to work, the scope of the variable diff needs to be enlarged, as done above. Alternatively you could add diff to the arguments passed to Promise.all, so you get access to diff as a promised value:

    function deleteUIDsFromDBForKey(rootkey, users_uids) {
      return retrieveUIDsFromDBForKey(rootkey)
        .then(uids => {
          let diff = uids.diff(users_uids)
          let deletes = []
          diff.forEach(key => {
            deletes.push(firebase.database().ref(rootkey + "/" + key).remove())
          })
          return Promise.all([diff, ...deletes])
        })
        .then(([diff]) => {
          return diff
        })
    }
    

    Unrelated to your question, but you could use map instead of forEach with push:

      let deletes = diff.map(key => {
        return firebase.database().ref(rootkey + "/" + key).remove()
      })