6

The spec says:

However, note that connectedCallback can be called more than once, so any initialization work that is truly one-time will need a guard to prevent it from running twice.

What does this mean? Is it saying that connectedCallback can be called more than one time (by the browser engine) before disconnectedCallback is ever called?

If there is always one connectedCallback for every disconnectedCallback, then that statement is rather pointless.

I will obviously clean up whatever I create in connectedCallback in disconnectedCallback, thus I will not have things "running twice".

trusktr
  • 44,284
  • 53
  • 191
  • 263
  • You can detach a node from the dom, and reattach it. I don't think it can run twice without the disconnected handler running. And I don't think it's pointless: plenty of people don't really understand cleaning up after oneself, even if you do. – Jared Smith Feb 25 '19 at 20:36
  • Haha, well, I don't think those people would be the ones reading the spec anyways. – trusktr Feb 25 '19 at 20:39
  • Good point. Touche. – Jared Smith Feb 25 '19 at 20:40
  • The spec doesn't guarantee that the disconnectedCallback will be executed before the connectedCallback. So if you rely on this asumption you may experiment son unwanted side effects. – Supersharp Feb 26 '19 at 22:29
  • @Supersharp Do you mean the order of calls could be `constructor --> connectedCallback --> connectedCallback --> disconnectedCallback`, or similar? Does any browser ever do that in practice? If so, in which case? Doesn't seem like a good idea for any browser to do that. – trusktr Feb 26 '19 at 23:10
  • @trusktr yes it's what i see with Chrome (ie when adding some HTML via `innerHTML+=` of via `insertAdjacentHTML`). – Supersharp Feb 28 '19 at 13:15
  • @Supersharp I'm not able to reproduce that in Chrome. Here's a fiddle showing one `connected` for every `disconnected` every time we use `innerHTML+=`, and one extra `connected` for the element we added: https://jsfiddle.net/xf82umas. Do you have a fiddle that shows more than one `connectedCallback` per `disconnectedCallback`? – trusktr Feb 28 '19 at 22:19
  • @trusktr you can see in your example that on Chrome (unlike Firefox) the disconnectedCallback are all called after connectedCallback. That (doesn't) work also with only one element: https://jsfiddle.net/wg9mfkyc/ – Supersharp Feb 28 '19 at 22:39
  • @Supersharp I see the same behavior in Firefox as I do in Chrome, with my fiddle: for each interval, I see only one extra `connected` than `disconnected`, which means it calls disconnectedCallback on every element that was connected, then connectedCallback on all of those again, then one additional connectedCallback for the new element. It's the same in Firefox. As for your example, it works as expected in both browsers, and every connected has one disconnected before the next connected. I don't see the problem you're mentioning. – trusktr Feb 28 '19 at 23:08
  • @Supersharp The only difference I see is that Chrome fires disconnected callbacks _after_ connected callbacks, whereas Firefox seems to do it in opposite order, but nonetheless, for every disconnectedCallback call there is a reciprocal connectedCallback call. Are you looking at the number on the right side of Firefox console that show the duplicate console.log counts? – trusktr Feb 28 '19 at 23:09
  • that's what i said – Supersharp Feb 28 '19 at 23:16
  • I don't get it. You said there could be more than one `connectedCallback` call per `disconnectedCallback` call, but in my example, and in your example, I don't see that happening in either Firefox or Chrome. What I see is one `connectedCallback` per every `disconnectedCallback`. – trusktr Feb 28 '19 at 23:54
  • @Supersharp (continued from see previous comment) In other words, I thought you said there can be cases where we see `constructor --> connectedCallback --> connectedCallback --> disconnectedCallback` for a given element (as per https://stackoverflow.com/questions/54874212#comment96560155_54874212), but your example doesn't demonstrate that, and I see `constructor --> connectedCallback --> disconnectedCallback`. – trusktr Feb 28 '19 at 23:54
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/189238/discussion-between-trusktr-and-supersharp). – trusktr Feb 28 '19 at 23:55

1 Answers1

4

All depends on what you're doing in the callbacks, and how many attach/detach events you might reasonably expect. If it's really complex, and if your node might be moved around a lot in the DOM, then it's definitely worth considering events versus renders. In other words, event loop considerations. Take the following example:

var square = document.createElement('custom-square');
var one = document.getElementById('one');
var two = document.getElementById('two');
one.appendChild(square);
two.appendChild(square);
one.appendChild(square);
two.appendChild(square);

In this example you would get several connectedCallbacks and several disconnectedCallbacks: one for each appendChild. However all of these back-to-back appendChild calls are all happening in the same cycle of the event loop.

So while you get four separate connectedCallback calls and also three separate disconnectedCallback calls, the node is only rendered once, appended to #two.

This won't always be a concern, but since most modern browsers try to render at 60 FPS, that means you've got less than 17ms per render cycle to do all of your JavaScript, and for the browser to do all of its parsing/flowing/rendering for a given frame.

If it becomes a concern, you could guard against these sorts of things by deferring appropriate work to a requestAnimationFrame callback, and then cancel that rAF if you have future connectedCallback events before the next render event, since you probably only care about the very last one.

David784
  • 7,031
  • 2
  • 22
  • 29
  • Hello David, thanks for the answer. That's basically my expectation as well. I modified the question title, as I'm specifically wondering if there is any case in which a connectedCallback can be called more than once before the same element's disconnectedCallback is fired. I would hope this isn't the case, but just want to make sure. – trusktr Mar 05 '19 at 22:26