简体   繁体   English

Promise allSettled running before promise finally

[英]Promise allSettled running before promise finally

I have a function that tries to load web images and tracks the count of loaded images and the count of the failed images.我有一个 function 尝试加载 web 图像并跟踪加载图像的计数和失败图像的计数。 I am loading the images using fetch and using Promise.allSettled to run operations after all the images are validated.我正在使用fetch加载图像,并在验证所有图像后使用Promise.allSettled运行操作。

const data = ["/test1.png", "/test2.png", "/test3.png"];
let imagesValidated = 0;
let imagesFailed = 0;
const promiseArr = [];

data.forEach((item) => {
  const imgPromise = fetch(item);
  promiseArr.push(imgPromise);

  imgPromise
    .then((resp) => {
      if (!resp.ok()) imagesFailed += 1;
    })
    .catch((error) => {
      imagesFailed += 1;
    })
    .finally(() => {
      // For the last image `test3.png`, the finally blocks runs after `allSettled`.
      imagesValidated += 1;
    });
});

Promise.allSettled(promiseArr).then(() => {
  // some operations
});

The issue I am facing is with the finally block.我面临的问题是 finally 块。 For the last image the finally block is running after the allSettled callback.对于最后一张图片,finally 块在allSettled回调之后运行。 This causes the imagesValidated to be lesser than the actual images scanned count.这会导致imagesValidated小于实际扫描的图像数。 I do not want to remove the finally block as in the future I will be adding more cleanup code into it.我不想删除 finally 块,因为将来我会在其中添加更多清理代码。

Is this the expected behavior of the Promise resolution methods?这是 Promise 解析方法的预期行为吗? Is there a way I can fix this code without removing the finally block?有没有一种方法可以在不删除 finally 块的情况下修复此代码?

You're pushing the fetch Promise to the array - not the chain that goes through .then and .finally .您正在将fetch Promise 推送到数组 - 而不是通过.then.finally的链。 Push the whole chained Promise to the array.将整个链式 Promise 推入数组。

data.forEach((item) => {
  promiseArr.push(
  fetch(item)
    .then((resp) => {
      if (!resp.ok()) imagesFailed += 1;
    })
    .catch((error) => {
      imagesFailed += 1;
    })
    .finally(() => {
      // For the last image `test3.png`, the finally blocks runs after `allSettled`.
      imagesValidated += 1;
    })
  );
});

Promise.allSettled(promiseArr).then(() => {
  // some operations
});

Or, even better, use .map on the original data instead.或者,更好的是,对原始数据使用.map

Promise.allSettled(
  data.map(item => fetch(item)
    .then((resp) => {
      if (!resp.ok()) imagesFailed += 1;
    })
    .catch((error) => {
      imagesFailed += 1;
    })
    .finally(() => {
      // For the last image `test3.png`, the finally blocks runs after `allSettled`.
      imagesValidated += 1;
    })
)
  .then(() => {
    // some operations
  });

Though, note that using Promise.allSettled isn't helping you that much here - none of the Promises can reject due to the .catch .不过,请注意,使用Promise.allSettled在这里对您没有多大帮助 - 由于.catch ,Promises 都不能拒绝。 Consider either using Promise.all , or use Promise.allSettled with just the .fetch , so you can increment the counters after all responses have come back.考虑使用Promise.all ,或仅使用Promise.allSettled .fetch ,这样您就可以在所有响应都返回后递增计数器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM