1

I am trying to make a bunch of nested calls to the database and want to do something once the results have all come back. I'm new to promises so forgive me if I'm totally doing this wrong (probably the case)

My code currently is something like this:

getVideos(user).then((videos) => {
  videos.forEach((video) => {
    getImage(video).then(() => {
      getMembers().then((members) => {
        getComments().then((comments) => {
          getKeywords().then((keywords) => {
            getTranscript().then((transcript) => {
              console.log(members, comments, keywords, transcript)
            }
          }
        }
      }
    })
  })
})

This is obviously super inefficient because getMembers(), getComments(), getKeywords(), and getTranscript() dont need to wait for each other and can all be called asynchronously. Also getImage() can be called asynchronously for every video in the loop without waiting.

I'm trying to change the code to bundle up these promises into one big one so once it resolves I can access all the fetched data in one place. This is my attempt but it prints

Promise{...}, Promise{...}, Promise{...}, Promise{...}

instead of the fetched data.

Any idea what I'm doing wrong and how I can properly change all these nested promises into one? Thanks

let members, comments, keywords, transcript

getVideos(user).then((videos) => {
   let promises = []
   videos.forEach((video) => {
      let p = getImage(video).then(() => {
        members = getMembers()
        comments = getComments()
        keywords = getKeywords()
        transcript = getTranscript()
        return Promise.all([members, comments, keywords, transcript])
      })
      promises.push(p)
  })
  return Promise.all(promises)
})
.then(() => {
  console.log(members, comments, keywords, transcript)
})
6
  • What if you console.log(arguments); instead? Commented Jul 25, 2018 at 23:56
  • You'll need to set global state with the data the embedded promises ( members, comments...) resolve with and print contingent on this state or move the output routines into .then handlers for said promises. Commented Jul 25, 2018 at 23:59
  • The end-solution will definitely depend on what you need, but I'd recommend taking a look at Promise.all. It allows you to wait for multiple promises before continuing execution. So if you want to concurrently retrieve all of the information about a particular video, you can. If you want to wait for all of the video information to have returned, you can do that do. Commented Jul 26, 2018 at 0:00
  • It's not clear what depends on what here. getMembers(), getComments(), getTranscript(), etc. don't take any arguments. So do they always return the same thing? Do they depend on anything happening before calling them? Are they reading a global variable? Commented Jul 26, 2018 at 0:05
  • If you want to serialize your requests, then chain your promises. Return the inner promises. Search for "promise chaining" to get more info. But, you probably don't need to serialize them. You can issue all the requests and use Promise.all() to know when they are all done. Commented Jul 26, 2018 at 0:14

1 Answer 1

6

Try using two Promise.alls instead - one for each video, and one for the members, comments, keywords, and transcript:

getVideos(user).then((videos) => Promise.all(
  videos.map(video => getImage(video)
    .then(videoResp => Promise.all([
      getMembers(), // do you need to call these functions with `videoResp`?
      getComments(),
      getKeywords(),
      getTranscript(),
    ]))
  )
));

The promise chain will then resolve with something like

[ [
    // video 1
    v1members,
    v1comments,
    v1keywords,
    v1transcript,
  ],
  [
    // video 2
    v2members,
    v2comments,
    v2keywords,
    v2transcript,
  ],
  // ...
]
Sign up to request clarification or add additional context in comments.

3 Comments

One might ask why getImage() can't be parallelized along with getMembers(), getComments() and so on all in the same Promise.all() since none of these seem to depend upon one another.
Good question, should have clarified: If there is no image I abort the query. No image = no need to get all other stuff
@EgorEgorov - Does "no image" mean that getImage() rejects or does one have to check the return value when it resolves?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.