Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript Promise resolving in catch block

I have a function sendMail that returns a promise.

module.exports = function sendMail(mailData) {

const smtpConfig = {
 service: 'gmail',
 auth: {
   user: MAIL_USER,
   pass: MAIL_PASS
 }
};

const trans = nodemailer.createTransport(smtpConfig);

return new Promise((reject, resolve) => {
 trans.sendMail(mailData, (err, result) => {
   if (err) {
     console.log('error', err)
     reject(err);
   }
   else {
     console.log('no error', result)
     resolve(result);
   }
  });
 });
}

The promise resolves and the logged output from this is:

no error { accepted: [ '[email protected]' ],
rejected: [],
response: '250 2.0.0 OK 1488900621 j79sm6419250itb.0 - gsmtp',
envelope: { from: '', to: [ '[email protected]' ] },
messageId: '<[email protected]>' }

And the email is sent. However calling the function from another module, the result gets passed to the .catch block as an error.

 module.exports = User = {

 sendMail(mailData)
   .then((result) => {
     console.log('here', result)
   })
   .catch((err) => {
     console.log('error', err)
   });

}

Produces the identical output but as an error in the catch block:

error { accepted: [ '[email protected]' ],
rejected: [],
response: '250 2.0.0 OK 1488900621 j79sm6419250itb.0 - gsmtp',
envelope: { from: '', to: [ '[email protected]' ] },
messageId: '<[email protected]>' }

And the .then block never runs.

Any help as to what I'm missing here is greatly appreciated.

like image 535
R. Erickson Avatar asked Mar 07 '17 15:03

R. Erickson


1 Answers

Here:

return new Promise((reject, resolve) => {

you mixed up the order of function parameters. Your function will be passed resolve first and reject second no matter how you name it, so your resolve will act as reject and vice versa.

It should be:

return new Promise((resolve, reject) => {

The names of the arguments to the function that you pass to the Promise constructor doesn't matter, but the order matters. So for example you can use this to produce a resolved promise:

new Promise((x, y) => x(123));
// same as Promise.resolve(123);

or this to produce a rejected promise:

new Promise((x, y) => y(123));
// same as Promise.reject(123);

but if you switch the x and y then it will be different - now x rejects:

new Promise((y, x) => x(123));
// same as Promise.reject(123);

and y resolves:

new Promise((y, x) => y(123));
// same as Promise.resolve(123);

See the docs:

  • https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise

Syntax

new Promise( /* executor */ function(resolve, reject) { ... } );

So the mystery is not why it doesn't work but why it works in some other module. Maybe it does something like:

Promise.reject(3).catch(e => e).then(val => console.log('val:', val));

but using your function instead of Promise.reject(3) and using some other logic instead of console.log, of course.

like image 184
rsp Avatar answered Sep 20 '22 03:09

rsp