Your while loop is a loop that keeps JavaScript busy during one second. During that time no other JavaScript code can execute, no matter what else you had planned for execution. In your case this means that the second func('ooo', 5) does not get launched until the first call has returned.
In practice, the callback you provide to new Promise should not be a blocking piece of code: it should execute relatively quickly and return. It's job is mostly to call some (low-level) API that will trigger an asynchronous event, to which your code will listen. At that time resolve can be called.
You can use the Web API for this (or some other asynchronous library's API), which gives you setTimeout: that function will allow you to be notified when the delay (e.g. 1 second) has passed, but still executes the rest of your code to completion (which can possibly also call setTimeout).
If you would resolve a promise when setTimeout calls its callback, then you have a useful, non-blocking implementation of delayOneSecond. It can then be combined easily with await:
const delayOneSecond = () => new Promise(resolve => setTimeout(resolve, 1000));
const func = async (name, num) => {
for(let i=1; i<=num; i++){
await delayOneSecond();
console.log(`[${name}] - ${num - i}`);
}
return "OK";
}
Promise.all([func('xxx', 5), func('ooo', 5)])
.then((res) => { console.log(res); })
Although it may seem here that the execution of func still takes 5 seconds before it returns, this is actually not true. It returns when it arrives at the first await. It returns a promise at that time (so without any delay), and execution can continue with the second call of func.
The two function execution contexts get restored when their delayOneSecond() promises resolve, i.e. after (at least) one second. Only then their for loops continue... This happens one after the other: they don't run their JavaScript in parallel: one function context gets restored, does its thing until the next await, and then the same happens with the other function context.