0
\$\begingroup\$

I am using one line arrow functions a lot, if they are well written I believe they can make code easier to read. I believe that the following code can be easily transformed into one liner but I can't figure out how. Any ideas please? I am asking more just from curiosity.

const getUID = async () => {
 let uid;
 await firebase.auth().onAuthStateChanged(async (user) => {
 if (!user) await firebase.auth().signInAnonymously();
 uid = user.uid;
 });
 return uid;
};
asked Nov 23, 2020 at 19:30
\$\endgroup\$
4
  • 3
    \$\begingroup\$ No, it can't, and probably shouldn't. The real problem is that onAuthStateChanged expects a callback and is supposed to be used as an observable that can fire multiple times, but you're trying to use it as a promise, waiting for the first change only. You would need to immediately unsubscribe, similar to this code. Also you should not pass an async function as a callback. \$\endgroup\$ Commented Nov 23, 2020 at 19:39
  • \$\begingroup\$ Ah, yeah, I forget that onAuthStateChanged is not one time job. Thanks for explaining! \$\endgroup\$ Commented Nov 23, 2020 at 19:50
  • \$\begingroup\$ There is no syntactic rule that would force you to use new line characters. You can write entire applications as one liners. Whether you should is a different story. Don't let number of lines become your holy grail. \$\endgroup\$ Commented Nov 24, 2020 at 5:57
  • \$\begingroup\$ The current question title, which states your concerns about the code, applies to too many questions on this site to be useful. The site standard is for the title to simply state the task accomplished by the code. Please see How do I ask a good question?. \$\endgroup\$ Commented Nov 24, 2020 at 8:26

1 Answer 1

1
\$\begingroup\$

First of all, onAuthStateChanged expects a callback and can be fired multiple times. To resolve that you can use unsubscribe() after the first success.

Secondly, for your code to work, you need to wait for signInAnonymously. At the moment you assign it to a temporary variable, but I can't see it working. Because onAuthStateChanged accepts a callback that can be fired multiple times, it won't wait in the main scope. To solve this, I suggest using Promise constructor.

Finally, you call signInAnonymously, but you don't do anything with its response. You need to use user.uid if the user is logged in, otherwise you need to use signInAnonymously().user.uid

So the final solution:

const getUID = async () => new Promise(resolve => {
 const unsubscribe = firebase.auth().onAuthStateChanged(user => {
 unsubscribe();
 resolve(user ? user.uid : firebase.auth().signInAnonymously().then(v => v.user.uid))
 });
})
const uid = await getUID()

Explanation:

  1. Wrap everything to Promise and resolve it when we get uid
  2. Auth & listen on onAuthStateChanged
  3. Unsubscribe on the first onAuthStateChanged callback trigger (because one trigger it's enough in your case)
  4. Check if a user is defined (that means the user is signed in), resolve promise with user uid
  5. If the user is not defined, use signInAnonymously to sign anonymous user, resolve that user `uid.
answered Nov 24, 2020 at 8:06
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.