0

I'm reading this article on promise chaining in Javascript, and am confused about the section where it says how can we do something after the avatar has finished showing and gets removed? For instance, we’d like to show a form for editing that user or something else. As of now, there’s no way.

Is the reason that we can't do something after the image gets removed that img.remove() doesn't return a promise? Or is it that setTimeout doesn't return anything after its callback is finished?

gkeenley
  • 2,920
  • 1
  • 18
  • 45
  • `you can't set code to execute after the callback of setTimeout?` because it runs asynchronously - do what you need inside the callback – Jaromanda X May 01 '20 at 02:40

1 Answers1

2

What it's saying is that, by using the code in the example:

setTimeout(() => img.remove(), 3000); // (*)

Using that code exactly, you can't detect when the image gets removed and do something when it occurs - its asynchronous removal is disconnected from the outer Promise chain.

The article's recommendation to fix it is to have the constructed Promise resolve when .remove() is called:

setTimeout(() => {
  img.remove();
  resolve(githubUser);
}, 3000);

Or you could put more code inside the setTimeout to run exactly when the image gets removed.

setTimeout(() => {
  img.remove();
  console.log('removed');
}, 3000);

If you don't do either of the above, and instead have just the setTimeout(() => img.remove(), 3000);, the asynchronous action that occurs after 3 seconds can't do anything except remove the image - which is usually a mistake. For example, if you wanted to chain another .then onto it which runs when the image gets removed, and the image needs to be removed after 3 seconds

.then(() => {
  // what logic to put in here to ensure next .then runs after 3 seconds?
  setTimeout(() => {
    img.remove();
  }, 3000);
})
.then(() => {
  console.log('image removed');
});

When inside a .then, to have the next .then run after a delay, you must return a Promise from the above .then, and that Promise must resolve after the delay is over.

.then(() => {
  // what logic to put in here to ensure next .then runs after 3 seconds?
  return new Promise((resolve) => {
    setTimeout(() => {
      img.remove();
    }, 3000);
  });
.then(() => {
  console.log('image removed');
});

If you don't return a Promise from the upper .then, or if you don't return anything at all, the lower .then will run immediately, as soon as the upper .then finishes, which you don't want.

CertainPerformance
  • 260,466
  • 31
  • 181
  • 209