One thing to remember (a very important thing) is that Promises are for asynchronous code.
But Javascript code is synchronous and blocking, in general. Unless you are using things like fetch() or XHR requests, or doing things in a worker process.
Also, another important thing to remember is that the function you pass to
new Promise();
Is executed immediately before the promise even returns. This being a very long, blocking bit of code will stop all other code from executing.
So the way you have it structured means it will always execute your entire time-consuming array loop, before ever returning the promise. You will never get the result you want with that approach.
This means you have to do something to get your code to give up control for a bit so other stuff can execute. This could be, as suggested above, a generator, where you can yield to other code, or you can use something as simple as setTimeout.
setTimeout essentially says, I would like to execute function x, y milliseconds from now. Of course JS is blocking, and other code may be running, so that really means as “as soon as possible - but no earlier than y milliseconds”.
What using setTimeout does is free up the JS engine to continue processing other code. It takes the function passed to it and puts it at the end of the queue of functions that need processing and will process it as soon as possible after the specified time has passed. It has the effect of making your code asynchronous.
If you re-arranged your function to process in chunks, you could get the result you are after. (This also has the handy effect of not freezing your interface and allowing you to update the interface based on processing progress as well).
This example could be cleaned up a bit more, but I’ve put a solution for it on codepen here:
A promise based loop processor.
Hope that helps!
~Micheal