Tuesday 11 April 2017

Why are these nested promises not working?

I am writing a process to be run on a cron job in a node environment.

The process fetches two lists of users from two external services, writes to file, and will do some comparison.

One of the sources for users is a Discourse forum, and unfortunately, to get the full user list, we have to fetch multiple trust_level lists and concatenate them.

I structured this using various nested promises and Promise.all. However, the function below is calling its then callback too early, before forumList.json and databaseList.json even exist... What am I doing wrong here?

import superagent from 'superagent'
import { writeFileSync } from 'fs'

export default function fetchData() {

  const process = []

  const databaseFetch = new Promise((resolve, reject) => {

    superagent.get('https://our-api.com/api/1/databases/our-db/collections/users')
      .end((error, response) => {

        if (error) {
          reject(error)
        } else {
          writeFileSync('temp/databaseList.json', JSON.stringify(response.body))
          resolve()
        }

      })

  })

  const forumFetch = new Promise((resolve, reject) => {

    // For reference, see https://meta.discourse.org/t/how-do-i-get-a-list-of-all-users-from-the-api/24261/8
    // We have to do this because of the way the discourse API is built
    const discourseApiList = [
      'trust_level_0',
      'trust_level_1',
      'trust_level_2',
      'trust_level_3',
      'trust_level_4',
    ]

    let forumList = []

    const discoursePromises = discourseApiList.map((trustLevel) => {

      return new Promise((resolveInner, rejectInner) => {
        superagent.get(`https://our-website.com/forum/groups/${trustLevel}/members.json`)
          .end((error, response) => {

            if (error) {
              rejectInner(error)
              reject()
            } else {
              forumList = forumList.concat(response.body.members)
              resolveInner()
            }

          })
      })

    })

    Promise.all(discoursePromises).then(() => {
      writeFileSync('temp/forumList.json', JSON.stringify(forumList))
      resolve()
    })

  })

  process.push(databaseFetch)
  process.push(forumFetch)

  Promise.all(process)

}



via John Doe

No comments:

Post a Comment