0

im trying to execute multiple pormises in chunks using promise all => this is just a code example - throwing every time getting the number 72. i have a simple catch in the function that calls executePromises but it does not catch as it should. the problem is that even if the first promise chunk fails the second one is also executed. so, all the promises execute and it the fail happens in 2 chunks i get an unhandled exception. if only 1 chunk fails then the catch is correct and it works fine. in debug, even if a promise is rejected it continue to run the chunks - i think its because they run sort of in "parallel", but if there are 2 errors in the same chunk it does not throw twice so makes sense.

i tried also using a .catch for the promise all but it didnt help either , the second chunk does not get there. also tried throwing an error inside the same catch also didnt help.

class testClass{  
async test(num: number): Promise<{ failed_skus: { id: string }[] }> {
  return new Promise((resolve, reject) => {
  setTimeout(() => {
    if (num === 72) {
      reject(new Error(`index : ${index}, num : ${num}`));
      index++;
    } else {
      resolve({ failed_skus: [{ id: 'str' }] });
      index++;
    }
  }, 1300);
});
}

async executePromises(): Promise<void> {

index = 0;
const productUpdateRequests = [
  72,
  900,
  3,
  4,
  5,
  6,
  72,
  800,
  9,
  1,
  2,
  3,
  4,
  5,
  6,
  7,
  8,
  9,
  1,
  2,
  3,
  4,
  5,
  6,
  72,
  100,
  9,
  1,
  2,
  3,
  4,
  5,
  6,
  7,
  8,
  9,
  1,
  2,
  3,
  4,
  5,
  6,
  7,
  8,
  9,
  1,
  2,
  3,
  4,
  5,
  6,
  7,
  8,
  9,
];

const productsUpdatesRequestsPromises = productUpdateRequests.map(this.test.bind(this));

const requestChunks = chunk(
  productsUpdatesRequestsPromises,
  20,
);
for (const requestChunk of requestChunks) {
  const updateStockResponses = await Promise.all(requestChunk);
}

} }

  • You're creating all the promises and starting all the timeouts in this line: `productUpdateRequests.map(this.test.bind(this))`. Chunking afterwards won't help. – Bergi Jul 26 '22 at 16:47

1 Answers1

1

The binding and setup of the promises was confusing me. Here is a working version of your code.

You probably needed this.index in your bound test() function (not just 'index'). I did not make it a class variable as, due to NodeJS timing, I'm not sure you could have guaranteed the order would match the array. My version just uses the array index.

Also, I found that mapping all the test functions at once started running them all at once, essentially finishing the program after 1.3s. In my code I only started the test function for the chunk I was on, so each chunk takes 1.3s.

Oh, and I didn't see a chunk() function, so I made one.

I hope you find this helpful. Happy coding!

function chunk(array, chunkSize) {
  let chunks = []
  for (let i = 0; i < array.length; i += chunkSize) {
    chunks.push(array.slice(i, i + chunkSize))
  }
  return chunks
}
class testClass {
  async test(num, idx) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (num === 72) {
          reject(new Error(`index : ${idx}, num : ${num}`))
        } else {
          resolve({ failed_skus: [{ id: 'str' }] })
        }
      }, 1300)
    })
  }

  async executePromises() {
    let processedChunks = 1
    const productUpdateRequests = [
      72, 900, 3, 4, 5, 6, 72, 800, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 72, 100, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3,
      4, 5, 6, 7, 8, 9,
    ]

    const requestChunks = chunk(productUpdateRequests, 20)
    for (const requestChunk of requestChunks) {
      const updateStockResponses = await Promise.all(requestChunk.map((num, idx) => this.test(num, idx)))
        .then(() => {
          console.log('Finished processing chunk ' + processedChunks)
        })
        .catch((error) => {
          //console.log(error)
          console.log('Error processing chunk ' + processedChunks)
        })
      processedChunks++
    }
  }
}

let c = new testClass()
c.executePromises()
clay
  • 5,917
  • 2
  • 23
  • 21
  • thanks very much this was very helpful! is there any chance you tell me how did you debug/ find out the problem – Rawi Lahiany Jul 27 '22 at 09:55
  • I copied your code and tried to make it run, but parts were missing so it wouldn't start without exceptions. Then I wanted to solve it and ran into the issues from my answer, in the order there. `this` is a big gotcha in javascript, along with classes (sometimes) and binding and Promises. I broke it apart so it made sense to me and what I thought you were trying to emulate. – clay Jul 27 '22 at 22:05