Theo
Theo

Reputation: 473

Asynchronous call inside a promise

First of all I know this question has been asked many times, but I can't figure how to do this. I am new to Node.js and dealing with the asynchronous aspect of it.

Here is my code

passport.use(new LocalStrategy({ usernameField: 'email', passwordField: 'password' }, function (email, pass, done) {   
    Users.query(email).exec(function (err, item) {
        const message = 'Login Invalid';
        if (err) return done(err);

        var promise = GetHash({ item, pass });        
        promise.then((data) => {                        
            return done(null, data)
        }).catch((err) => {
            console.log(err);
            return done(null, false, { message });
        });                             
    });    
}));

function GetHash(userPasswordRequest) {
    return new Promise(function (resolve, reject) {
        if (userPasswordRequest.item && userPasswordRequest.item.Items[0]) {
            var userRecord = userPasswordRequest.item.Items[0].attrs;
            if (userRecord.old) {
                if (crypto.createHash('sha256').update(userPasswordRequest.pass, 'ucs-2').digest('base64') === userRecord.password) {
                    var newHash = bcrypt.hashSync(userPasswordRequest.pass, 10);
                    Users.update({ email: userRecord.email, password: newHash, old: null }, function (err, newItem) {
                        if (err) { console.log(err); } else {
                            console.log('first call');
                            resolve(newItem.attrs);
                        }
                    });                
                }
            }
            else {
                if (bcrypt.compareSync(userPasswordRequest.pass, userRecord.password)) {
                    console.log('first call');
                    resolve(userPasswordRequest.item.Items[0].attrs);                    
                }
            }
        }
        reject();
    })
}

The issue is situated here :

 if (crypto.createHash('sha256').update(userPasswordRequest.pass, 'ucs-2').digest('base64') === userRecord.password) {
                    var newHash = bcrypt.hashSync(userPasswordRequest.pass, 10);
                    Users.update({ email: userRecord.email, password: newHash, old: null }, function (err, newItem) {
                        if (err) { console.log(err); } else {
                            console.log('first call');
                            resolve(newItem.attrs);
                        }
                    });                
                }

Because the Users.update is asynchronous, I'm rejecting the promise before resolving it.

I tried many things, a promise inside of a promise and many other stuff but I can't make this work properly.

Any help would be greatly appreciated

Upvotes: 0

Views: 537

Answers (1)

robertklep
robertklep

Reputation: 203286

You shouldn't use reject as a fall-through, but call is explicitly when an error condition occurs.

So like this:

if (userPasswordRequest.item && userPasswordRequest.item.Items[0]) {
  ...
} else {
  return reject(Error('invalid userPasswordRequest'));
}

And also:

if (bcrypt.compareSync(userPasswordRequest.pass, userRecord.password)) {
  console.log('first call');
  return resolve(userPasswordRequest.item.Items[0].attrs);                    
} else { 
  return reject(Error('invalid password'));
}

This isn't right either:

if (err) { console.log(err); }

Don't just log the error, reject the promise with it:

if (err) {
  console.log(err);
  return reject(err);
}

As you can see, it's also good form to return after resolving or rejecting.

Upvotes: 1

Related Questions