My actual code is very complex but i will simplify this as much as i can:
let counter = 0
console.log("time counter: ", counter)
setInterval(() => {
counter = counter + 1;
console.log("time counter: ", counter)
}, 1000)
const myPromises =
[ new Promise((resolve, reject) => setTimeout(() => {
console.log("reject(1)")
reject(1)
}, 5 * 1000)) // after 5 seconds.
, new Promise(resolve => setTimeout(() => {
console.log("resolve(2)")
resolve(2)
}, 3 * 1000)) // after 3 seconds.
, new Promise(resolve => setTimeout(() => {
console.log("resolve(3)")
resolve(3)
}, 3 * 1000)) // after 3 seconds.
, new Promise((resolve, reject) => setTimeout(() => {
console.log("reject(4)")
reject(4)
}, 1 * 1000)) // after 1 second.
]
async function testIt(){
const results = myPromises.map(async promise => {
return new Promise((resolve) => {
// no matter what happens with the individual promise itself, we resolve.
promise
.then(ok => {
resolve({ wasSuccessful: true, result: ok })
})
.catch(err => {
resolve({ wasSuccessful: false, error: err })
})
})
})
// should be no need to catch anything here. use await.
const results_ = await Promise.all(results)
console.log("results_: ", results_)
}
testIt()
.catch(err => console.log("this error isn't supposed to happen error: ", err))
I essentially want the following:
1. start the first promise( myPromises[0] ). Wait 5 seconds. After that reject it.
2. start the next promise( myPromises[1] ). Wait 3 seconds. Resolve it.
At this point we have 8 seconds on the counter.
3. start the next promise( myPromises[2] ). Wait another 3 seconds. Resolve it.
At this point we have 8 + 3 = 11 seconds on the counter.
4. start the next promise ( myPromises[3] ).. Wait for 1 second.. resolve it.
I guess you go the idea.. How to do this now?
Note this is not then().then().then()
.. im not reducing/accumulating this list as i seen in other questions on this topic. I don't want this to be rejected for any reason.
Instead i want a list of results. Like this:
results_: [
{ wasSuccessful: false, error: 1 },
{ wasSuccessful: true, result: 2 },
{ wasSuccessful: true, result: 3 },
{ wasSuccessful: false, error: 4 }
]
But note my console.log output .. even if i get the right result, it shows the real execution order:
time counter: 0
time counter: 1
resolve(4)
time counter: 2
resolve(2)
resolve(3)
time counter: 3
time counter: 4
reject(1)
results_: [
{ wasSuccessful: false, error: 1 }, // note the array ordering is correct. rejected,
{ wasSuccessful: true, result: 2 }, // resolved,
{ wasSuccessful: true, result: 3 }, // resolved,
{ wasSuccessful: false, error: 4 } // rejected. good.
]
time counter: 5
time counter: 6
time counter: 7
Basically this promises were fired in paralel, and whichever timeout is faster, is resolved faster.
Instead i wanted it to be like this:
time counter: 0
time counter: 1
time counter: 2
time counter: 3
time counter: 4
time counter: 5
reject(1)
time counter: 6
time counter: 7
time counter: 8
resolve(2)
time counter: 9
time counter: 10
time counter: 11
resolve(3)
time counter: 12
resolve(4)
results_: [
{ wasSuccessful: false, error: 1 },
{ wasSuccessful: true, result: 2 },
{ wasSuccessful: true, result: 3 },
{ wasSuccessful: false, error: 4 }
]
time counter: 13
time counter: 14
...
This is simplification. In practice, what i have list of 30k+ records - on which i need to perform some api action, and essentially resolve a promise. I grouped this list in sublists of 10 elements each. I'm gonna run in parallel each sublist.
But the big list.. aka the lists of lists.. needs sequence:
bigList = [ [ small parallel list 0 ], [ small parallel list 1 ] .. ]
Each promise in this parallel ones is very computationally intensive already. Im lucky if i can run 10 in parallel. So that's why the big list must be sequential. Or else it will fire a tree of promises with 30k leafs which will crash something.
Still not sure if at this scale is realistic but after i'm implementing this sequence i will be able to tell for sure.
So how to run this 4 promises above in sequence? Thanks.
All those promises begin at the same time, so you're running them in parallel
You could just have the executor
function of the promise in the array - then run the executor in a reduce
rather than a map
let counter = 0
console.log("time counter: ", counter)
let int = setInterval(() => {
counter = counter + 1;
console.log("time counter: ", counter)
}, 1000)
setTimeout(() => clearInterval(int), 15000);
const myPromiseExecutors =
[ (resolve, reject) => setTimeout(() => {
console.log("reject(1)")
reject(1)
}, 5 * 1000) // after 5 seconds.
, resolve => setTimeout(() => {
console.log("resolve(2)")
resolve(2)
}, 3 * 1000) // after 3 seconds.
, resolve => setTimeout(() => {
console.log("resolve(3)")
resolve(3)
}, 3 * 1000) // after 3 seconds.
, (resolve, reject) => setTimeout(() => {
console.log("reject(4)")
reject(4)
}, 1 * 1000) // after 1 second.
]
async function testIt(){
const results = await myPromiseExecutors.reduce(async (promise, exec) => {
const ret = await promise;
try {
const ok = await new Promise(exec);
ret.push({ wasSuccessful: true, result: ok });
} catch(err) {
ret.push({ wasSuccessful: false, error: err });
}
return ret;
}, Promise.resolve([]))
console.log("results_: ", results)
}
testIt();
to be honest, it's probably going to be cleaner to use a for...of
loop
let counter = 0
console.log("time counter: ", counter)
let int = setInterval(() => {
counter = counter + 1;
console.log("time counter: ", counter)
}, 1000)
setTimeout(() => clearInterval(int), 15000);
const myPromiseExecutors =
[ (resolve, reject) => setTimeout(() => {
console.log("reject(1)")
reject(1)
}, 5 * 1000) // after 5 seconds.
, resolve => setTimeout(() => {
console.log("resolve(2)")
resolve(2)
}, 3 * 1000) // after 3 seconds.
, resolve => setTimeout(() => {
console.log("resolve(3)")
resolve(3)
}, 3 * 1000) // after 3 seconds.
, (resolve, reject) => setTimeout(() => {
console.log("reject(4)")
reject(4)
}, 1 * 1000) // after 1 second.
]
async function testIt(){
const results = [];
const p = Promise.resolve();
for (let exec of myPromiseExecutors) {
try {
const ok = await new Promise(exec);
results.push({ wasSuccessful: true, result: ok });
} catch(err) {
results.push({ wasSuccessful: false, error: err });
}
}
console.log("results_: ", results)
}
testIt();