Using await within a Promise

Viewed 41337

There seems something inherently wrong with having to define a Promise's callback as asynchronous:

return new Promise(async (resolve, reject) => {
  const value = await somethingAsynchronous();
  if (value === something) {
    return resolve('It worked!');
  } else {
    return reject('Nope. Try again.');
  }
});

This is apparently an antipattern and there are coding problems which can arise from it. I understand that it becomes easier to fail to catch errors here, even when placing await statements inside try/catch blocks.

My first question is, what's the best way to code something like this, when one wants to forward a Promise with different resolve/reject values? With then/catch? I.e.

return new Promise((resolve, reject) => {
  somethingAsynchronous().then(value => {
    if (value === something) {
      return resolve('It worked!');
    } else {
      return reject('Nope. Try again.');
    }
  }); // errors would now be propagated up
});

Or do you just take it out the Promise constructor altogether as suggested here?

async function outerFunction() {
  const value = await somethingAsynchronous();
  return new Promise((resolve, reject) => {
    if (value === something) {
      return resolve('It worked!');
    } else {
      return reject('Nope. Try again.');
    }
  });
}

But what if you have several await statements in the outerFunction(), i.e. a linear code block calling several asynchronous functions. Would you then have to create and return a new Promise every time?

But then how do you account for code such as this?

async function outerFunction() {
  if (someSynchronousCheck()) {
    return 'Nope. Try again.' // another reject case
  }

  const value = await somethingAsynchronous();
  // ...
}

I have the feeling that I'm making this more complicated than it should be. I'm trying to avoid nesting callbacks/chaining then/catch blocks without creating more problems in the future.

My final question is, why is the callback passed to a Promise not inherently async? It is already wrapped within a promise and expects the resolve/reject functions to be called asynchronously.

3 Answers

You can also chain the promises yourself by simply doing this:

return new Promise((resolve, reject) => {
  somethingAsynchronous().then((value) => {
      if (value === something) {
        return resolve('It worked!');
      } else {
        return reject('Nope. Try again.');
      }
  }, (error) => { reject(error); });
});

I've been using this for some time and it works perfectly for me.

Related