1

I am chaining a few requests that return promises. The first one is a login check on some site that returns some credentials back. Then I making a admin.auth().createUser() call. After I know that this createUser call succeeds and that I know the login check succeeded, I want to use these two objects returned from both promises to make a third request to store information in firebase realtime database. I just dont know how to pass both those results to the final promise. Here's some code.

login(siteUser, sitePass)
   .then(credentials => {
      return admin.auth().createUser({
         'email': email,
         'emailVerified': false,
         'password': password,
         'displayName': username
       })
    })
    .then(userData => {
       return writeUserData(userData, credentials); // I need to pass credentials here but I don't know how.
    })
    .then(() => res.status(200).send('success'))
    .catch(err => res.status(500).send(err));

I need to pass the result from the first promise to writeUserData after createUser() resolves.

user1738539
  • 874
  • 2
  • 11
  • 23

3 Answers3

2

This is functionally equal to your code, except it passes credentials on to where it's needed for writeUserData. Rather than a completely flat promise chain, you add a .then to createUser response to return credentials rather than the unused (in your code) response from createUser

login(siteUser, sitePass)
.then(credentials => 
    admin.auth().createUser({
        email, 
        emailVerified:false, 
        password, 
        displayName: username
    })
    .then(userData => credentials)
)
.then(credentials => writeUserData(userRecord, credentials))
.then(() => res.status(200).send('success'))
.catch(err => res.status(500).send(err));

If, however, you've made a mistake in your code and

.then(userData => {
   return writeUserData(userRecord, credentials); // I need to pass credentials here but I don't know how.
})

was supposed to be

.then(userData => {
   return writeUserData(userData, credentials); // I need to pass credentials here but I don't know how.
})

(i.e. userRecord should've been userData) - then you are not ignoring the response from createUser - this doesn't make the code much more complex at all

login(siteUser, sitePass)
.then(credentials => 
    admin.auth().createUser({
        email, 
        emailVerified:false, 
        password, 
        displayName: username
    })
    .then(userData => ({userData, credentials}))
)
.then(({userData, credentials}) => writeUserData(userData, credentials))
.then(() => res.status(200).send('success'))
.catch(err => res.status(500).send(err));
Jaromanda X
  • 53,868
  • 5
  • 73
  • 87
  • Thanks! and yea it was a typo – user1738539 Jun 26 '17 at 00:35
  • cool, so the last code block should work – Jaromanda X Jun 26 '17 at 00:40
  • This didnt work as is. I needed to add return before admin.auth. Like the solution by @shivam – user1738539 Jun 26 '17 at 01:34
  • in that case, you copied the code incorrectly, a return there would be a syntax error as I'm using the shorthand arrow function notation which has an implicit `return` - notice the total lack of `{` after `=>` – Jaromanda X Jun 26 '17 at 02:15
  • Oh I see it now. One more thing. how can I properly catch the error from the return admin.auth().createUser()? If i simply add a catch and try to do res.send(err), the outer then's get executed. How can I finish the call in the inner catch or pass the catch to the outer one? – user1738539 Jun 26 '17 at 02:19
  • If you want to have an inner catch and also pass to outer catch then you throw in the inner catch. But the outer catch should be called in case of any rejection as the code stands now – Jaromanda X Jun 26 '17 at 02:20
  • OH it works now. Thanks! Idk what I did but I was getting unhandled promise rejection when that promise rejected but now it works. – user1738539 Jun 26 '17 at 02:36
1

The Promise.all solution by Maaz would also work, Unless you need something from the login request into the createUser request.If thats the case, then you could use the solution below.

login(siteUser, sitePass)
.then(credentials => {
  return admin.auth().createUser({
     'email': email,
     'emailVerified': false,
     'password': password,
     'displayName': username
   })
  .then(createUserRes => ({createUserRes, credentials})
})
.then(userData => {
    // You can now access both the createUserRes & credentials as
    // userData.credentials or userData.createUserRes
   return writeUserData(userRecord, credentials); // I need to pass credentials here but I don't know how.
})
.then(() => res.status(200).send('success'))
.catch(err => res.status(500).send(err));
Shivam
  • 3,462
  • 1
  • 15
  • 20
0

You can try this. You need to use Promise.all

const loginPromise = login(siteUser, sitePass);
const createUserPromise = admin.auth().createUser({
  'email': email,
  'emailVerified': false,
  'password': password,
  'displayName': username
})

Promise.all([loginPromise, createUserPromise]).then(result => {
    // Then use result array
    return writeUserData(result[1], result[0]);
  }).then(() => res.status(200).send('success'))
  .catch(err => res.status(500).send(err));
maazadeeb
  • 5,922
  • 2
  • 27
  • 40
  • this would execute `login` and `createUser` essentially in parallel - which possibly could cause problems if you take those function names to mean what they do :p – Jaromanda X Jun 25 '17 at 11:52