0

I am learning to make a web app; I'm building a toy project on firebase.

Say I have some code like this:

db.doc(`/users/${username}`).get()
  .then(doc => {
    if (doc.exists) {
      return res.status(400).json({message: "This username is already taken"});
    }
    return firebase.auth().createUserWithEmailAndPassword(username, password);
  })
  .then(data => {
    // Do additional processing here
  })
  .then(data => {
    return res.status(201).json({message: "New user created!"});
  })
  .catch(err => {
    res.status(500).json({error: err});
  });

It seems to me that in the first then, if I returned res, then the rest of the promise chain isn't executed. If I returned anything else, however, then the next function in the promise chain is passed the returned data and the chain keeps executing.

How does javascript (or maybe firebase?) know to distinguish between:

  1. when I return res, bail from the rest of the promise chain
  2. when I return anything but res, continue the promise chain's execution?
Tan Wang
  • 811
  • 1
  • 6
  • 16
  • `res` or `res.json` is not a promise, you should return a promise to continue the chain. – hoangdv Mar 08 '21 at 08:04
  • @hoangdv that's not true. You can always return a non-promise value in a promise chain. [Example](https://jsbin.com/xekihipobu/edit?js,console) – VLAZ Mar 08 '21 at 08:18
  • 2
    JavaScript *does* continue to execute the rest of the chain. What makes you think it doesn't? – Bergi Mar 08 '21 at 09:06
  • @Bergi Because the next `.then()` expects data in a certain shape. If given the `res` object, the next `.then()` in the chain fails, and would fall through to the `.catch()` and end up throwing a 500. – Tan Wang Mar 08 '21 at 17:03
  • 1
    @TanWang That's probably what happens, except that you won't get a 500 error since the code in the if statement already sent a 400 response. – Bergi Mar 08 '21 at 17:23
  • @Bergi I really doubt that - if I had e.g. some server-side logging in the `.catch()` block, I'd be logging a 500 no matter what happened in the earlier `.then()` blocks. – Tan Wang Mar 09 '21 at 05:12
  • @Bergi oop - I take that back. Looks like javascript _does_ continue to execute, even after I've sent `return res...` in an earlier `.then()` – Tan Wang Mar 09 '21 at 05:21
  • @Bergi I guess I'm still curious - if I had some side effect in the `.catch()` block, I'd be executing that side effect even for cases when I didn't really have an exception. Even if I already sent the `res.status(400)`, my `.catch()` still executes as if my own code had an unintended exception. Isn't that kind of misleading and surprising? – Tan Wang Mar 09 '21 at 05:24
  • @TanWang Yes, it does run. A `return` in a `then` handler doesn't skip the rest of chain, only the rest of the handler function. Use [proper nested control flow](https://stackoverflow.com/a/29500221/1048572) if you want to do the additional processing conditionally. – Bergi Mar 09 '21 at 09:23

0 Answers0