0
login() {
    return new Promise((resolve, reject) => {
        userCollection.findOne({email: this.data.email}).then((myUser)=>{
            if (myUser && myUser.password == this.data.password) {
                resolve("Congrats! Successfully logged in");
            } else{
                reject("Login failed");
            }
        }).catch(()=>{
            reject("Please try again later")
        })
    })
}

This is my model and I can use it to find data from Mongodb. I'm using express js. But, I want to know how I can use async await to do exactly the same thing that the above promise does. I mean, I would like to convert this code to async await way.

Any assistance would be highly appreciated.

zhulien
  • 5,145
  • 3
  • 22
  • 36
Rashel
  • 95
  • 6
  • 1
    Does this answer your question? [What is the explicit promise construction antipattern and how do I avoid it?](https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it) – ggorlen Feb 13 '21 at 16:30
  • 2
    I am afraid, no, it doesn't. – Rashel Feb 13 '21 at 16:50
  • 1
    You may not think so but I suggest another look. This code is a well-known antipattern: there's no reason to wrap a promise in `new Promise` as the dupe indicates. You can just `await` the promise you have or return it directly instead of adding an additional layer of indirection. Even if it didn't answer the question, I see no attempt here at adding the `async` or `await` keywords, so it seems like a "do it for me" request (off topic; too broad) rather than a "help me with my failing attempt" question (on topic). – ggorlen Feb 13 '21 at 18:41

1 Answers1

2

This should suffice:

async function login() {
   try {
      const user = await userCollection.findOne({ email: this.data.email });

      if (user && user.password === this.data.password) {
         // handle valid user
      }
      else {
         // handle not found user or password mismatch
      }
   }
   catch (error) {
      // handle or rethrow error
   }
}

Duplicating your case will result in:

async function login() {
   try {
      const user = await userCollection.findOne({ email: this.data.email });

      if (user && user.password === this.data.password) {
         return 'Congrats! Successfully logged in';
      }
      else {         
         throw new Error('Login failed');
      }
   }
   catch (error) {
      throw new Error('Please try again later');
   }
}

Then in your caller code you can await(or .then() it, but prefer await) the result of login:

try {
   const loginResult = await login();
}
catch(error) {
   // handle error
}

Note that in doing so, you will once again need to mark the caller function as async for you to be able to use the await operator.

zhulien
  • 5,145
  • 3
  • 22
  • 36
  • 1
    Why not do `....findOne({ email: this.data.email, password: this.data.password })`? – codemonkey Feb 13 '21 at 17:18
  • 1
    @codemonkey That's a valid point but I'm not sure that question should be addressed to me. The question is about converting promise syntax to `async`/`await` syntax. In any case, I agree this can be optimized. – zhulien Feb 13 '21 at 17:23
  • The design here is somewhat questionable. The db password should be hashed, so typically you'd retrieve the record, then use bcrypt or something to compare the plaintext password with the hash in the database. If your design is using plaintext passwords in the db, that's insecure and should be changed. Second design issue is that the UI and DB are too closely coupled. A login function shouldn't be responsible for determining which strings the user sees upon login, it should just return a boolean or object and/or throw errors and let some other part of the interface show the message. – ggorlen Feb 13 '21 at 18:19
  • 1
    @ggorlen Once again, you should address that to the author, not me. Also, I think you miss the point of the question entirely. – zhulien Feb 13 '21 at 18:36
  • 1
    @ggorlen The 'why not...' suggestion isn't coming from the author as you might see. In any case, it is a good practice to use mentions to address specific user's comment as it keeps the flow of the conversation cleaner and understandable. Furthermore, the duplicate suggestion isn't answering author's question, it just points out a bad practice he is using in his code. All in all - all the comments under this answer are not remotely connected to it and should have been placed on the question itself instead. – zhulien Feb 13 '21 at 18:49
  • 1
    @ggorlen I really don't understand what you're talking about. I haven't said design problems should be ignored. I just gave you a suggestion to use the mentions feature when you address someone for discussion's sake. And, like I said, you didn't address the question's author, you are addressing codemonkey and me and none of us are actually the OP(which is the author, by the way) so I suggested the comments are not connected to my answer and should be posted on the question itself. But we still disagree on the point that "you did answer the question and I didn't" but let's leave it at that. – zhulien Feb 13 '21 at 19:20
  • Hey guys, thanks all for your help and suggestions. I'm in learning process and I haven't yet learned about hashing/bcrypting etc. I intentionally used plain password for db here. But, yes, you are right. There shouldn't be plain password and there should be hashing. But, I was trying to use async await instead of regular promise. – Rashel Feb 14 '21 at 02:36