3

I have a function call like so:

await someFunction(foo);

With someFunction defined like:

const someFunction = foo => {
  return new Promise((resolve, reject) => {
    if (foo) {
      return resolve(someOtherPromise());
    }
    reject();
  }
}

Is this valid code? I have tested it and it seems ok.

Is it correct that await someFunction() will transform to await someOtherPromise() if foo is true i.e. will it continue waiting for someOtherPromise to resolve?

Kex
  • 8,023
  • 9
  • 56
  • 129
  • 2
    Promises are automatically flattened, you never have to deal with "a promise within a promise" - a `Promise>` is automatically merged to become `Promise`. – VLAZ Oct 01 '20 at 11:27
  • @VLAZ is it correct to return `resolve(someOtherPromise());` or is just `return someOtherPromise()` sufficient? – Kex Oct 01 '20 at 11:32
  • 1
    Returning from the promise executor *doesn't resolve it*. You have to call the `resolve` parameter. In fact, returning from the promise is pretty much irrelevant - the value isn't used anywhere (in this case) and the only data that the promise will produce is what you pass into `resolve()`. – VLAZ Oct 01 '20 at 11:34
  • Sorry, I mistyped. Forget the `return`. Do I need to call `resolve(someOtherPromise())` or can I just call `someOtherPromise()`? – Kex Oct 01 '20 at 11:38
  • Do you want the value from the other promise or not? If you do `p1 = new Promise(resolve => resolve(makeAnotherPromise()))` (let's assume `makeAnotherPromise` will eventually resolve to `42`) then what you get after `await p1` resolves is `42`. If you do `p2 = new Promise(resolve => { makeAnotherPromise(); resolve() })` then `p2` will resolve to `undefined` (you don't pass anything to `resolve`) also `makeAnotherPromise()` might still not be finished. – VLAZ Oct 01 '20 at 11:42

3 Answers3

4

Yes, it is valid code and works by resolving with a promise, but smells like the Promise constructor antipattern. I would instead recommend to write

function someFunction(foo) {
  if (foo)
    return someOtherPromise();
  else
    return Promise.reject();
}

or

async function someFunction(foo) {
  if (foo)
    return someOtherPromise();
  else
    throw;
}

(and better throw a new Error with a message, not undefined)

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
0

I've written some test code to see if it's true:

const someFunction = foo => {
  return new Promise((resolve, reject) => {
    if (foo) {
      return resolve(someOtherPromise(2000));
    }
    reject();
  });
}

const someOtherPromise = async(ms) => {
    return new Promise(resolve => setTimeout(() => {
        console.log("i'm about to resolve in someOtherPromise");
        resolve();
    }, ms));
}


const run = async () => {
    await someFunction('foo');
    console.log('finished waiting for someFunction');
}

run();
TKoL
  • 13,158
  • 3
  • 39
  • 73
0

I have written 3 function to test it out.

c = () => new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('c');
        resolve();
    }, 1000);
});
b = () => new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('b');
        resolve(c());
    }, 1000);
});

a = async () => {
    console.log('a before');
    await b();
    console.log('a after');
};

a();

As we can see, the output order is a before, b, c then a after. So await had waited for b and continued waiting for c.

namgold
  • 1,009
  • 1
  • 11
  • 32