-1

Consider the following promise array

const promiseArray = [1, 2, 3].map(num =>
  new Promise(async resolve => {
    while (num > 0) {
      await foo();
      num--;
    }
    await bar(num);
    resolve(); // No value to return
  })
);
const a = Promise.all(promiseArray);

Is the resolve function necessary?

Can we omit it and turn the promise into something like this?

const promiseArray = [1, 2, 3].map(num =>
  new Promise(async () => {
    while (num > 0) {
      await foo();
      num--;
    }
    await bar(num);
  })
);
const a = Promise.all(promiseArray);
Max
  • 414
  • 1
  • 4
  • 12
  • 1
    [Never pass an `async function` as the executor to `new Promise`](https://stackoverflow.com/q/43036229/1048572)! So simplify to just `const aPromise = foo(1,2,3);` or `const aPromise = Promise.resolve(foo(1, 2, 3));`. – Bergi Jul 26 '20 at 14:28
  • _Is the resolve function necessary?_ - without `resolve` function call, `aPromise` will never fulfill. To fulfill it, you have to call `resolve` function – Yousaf Jul 26 '20 at 14:28
  • 2
    Well, did you try it? Wait for `aPromise`. Your second snippet will not work. – Bergi Jul 26 '20 at 14:29
  • 2
    If foo returns a promise, which it must if you’re awaiting it, why are you wrapping it in another promise? – Mark Jul 26 '20 at 14:31
  • Thanks for the update, but "never" here really means never. And your second snippet still doesn't work when you try it. – Bergi Jul 26 '20 at 14:49
  • Do you realize that when you call `await bar(num)`, `num` is always `0`, so you can just call `await bar(0)`? Or, show us the real code, not this make-up code. – jfriend00 Jul 26 '20 at 15:07
  • It does not work well to change your question to a new question 2 hours after you posted the original. If you have something new to ask 2 hours later, please post a new question. In both of your new cases, your `promiseArray` is an array of `undefined` values because you aren't returning anything from the outer `.map()` callback. Also, I have no idea why you keep trying to make this so complicated when existing answers have shown you much simpler ways to do this. Since you have no actual asynchronous operations, it's kind of hard to say what actually "works" here. – jfriend00 Jul 26 '20 at 18:05
  • If you're trying to solve some problem that is more involved than the make-up code you show here, then we can only help you with that, if you show us your real code (in a new question). – jfriend00 Jul 26 '20 at 18:07

3 Answers3

2

Yes, calling resolve or reject is necessary when using the new Promise constructor, otherwise the promise will stay pending.

However, in your case, you shouldn't be using new Promise at all:

const promiseArray = [1, 2, 3].map(async num => {
  while (num > 0) {
    await foo();
    num--;
  }
  await bar(num);
});
const a = Promise.all(promiseArray);
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • I tried but it doesn't work without Promise constructor. Can you help check my code? I have updated the answer. – Max Jul 26 '20 at 15:56
  • 1
    @Max That's not the code from my answer. If you're doing something else, please [ask a new question](https://stackoverflow.com/questions/ask) with your *actual* code. Regarding the code in your update to the question, if you just want to do `array.flat().forEach(console.log)`, you should not use promises at all - there's nothing asynchronous! – Bergi Jul 26 '20 at 15:59
1

When you create the promise using constructor, first parameter should be called to resolve the promise, the second parameter(if present) to the function should be called to reject the promise. If you are not calling any of the params then promise will be in the pending state always. More information

I think you are confused with async/await and promises.

When you specify async function it will always return resolved promise unless you throw an error inside function which is not caught.

For example:

async function hello(){ return 1}
hello().then((val) => console.log(val));

The same example you can implement using promises

let promise = return new Promise((resolve) => return resolve(1));
promise.then((val) => console.log(val));
Akshay Bande
  • 2,491
  • 2
  • 12
  • 29
  • Actually my situation involves more than one Promise. Please check the question again. I have updated it. Thanks :) – Max Jul 26 '20 at 14:47
  • The same logic applies to promise.all. You have to resolve to get the result from promise.all, if you are not resolving you promise.all will never resolve or reject it will be in pending state always. – Akshay Bande Jul 26 '20 at 14:49
1

Can we omit it and turn the promise into something like this?

No, you cannot. Without calling resolve(), your new Promise() will never resolve. When you then call:

const a = Promise.all(promiseArray);

None of the promises in promiseArray will ever resolve. So, the promise a will never resolve. So, none of this will be of any use and you will have no way of knowing when everything is done executing.

It doesn't appear you really need to wrap anything in a promise here. You can just do this:

async function runLoop() {
    for (let i = 1; i <= 3; i++) {
        let num = i;
        while (num > 0) {
          await foo();
          num--;
        }
        await bar(num);    // note this will always be bar(0)
    }
}

runLoop().then(() => {
    console.log("all done");
}).catch(err => {
    console.log(err);
});

Or, if you want your separate loops to run in parallel, you can do this:

const promiseArray = [1, 2, 3].map(async num => {
  while (num > 0) {
    await foo();
    num--;
  }
  await bar(num);    // note this will always be bar(0)
});
Promise.all(promiseArray).then(() => {
    console.log("all done");
}).catch(err => {
    console.log(err);
});
jfriend00
  • 683,504
  • 96
  • 985
  • 979