1

I have two promises that get called when waiting for either A) an element to appear, or B) an element to disappear

 * Wait for DOM element to Disappear
 * @param {String} element DOM element to be watched
 */
export const elementVisibilityWatcherDisappear = ClientFunction((element) => {
    return new Promise(resolve => {
        var interval = setInterval(() => {
            if (document.querySelector(element)){
                return;
            }
            clearInterval(interval);
            resolve();
        }, 100);
    });
})

/**
 * Wait for DOM element to Appear
 * @param {String} element DOM element to be watched
 */
export const elementVisibilityWatcherAppear = ClientFunction((element) => {
    return new Promise(resolve => {
        var interval = setInterval(() => {
            if (!document.querySelector(element)){
                return;
            }
            clearInterval(interval);
            resolve();
        }, 100);
    });
})

What does document.querySelector(element) return? Doesn't it return null if the element wasn't found in the DOM? Thus for the method 'elementVisibilityWatcherDisappear' within the IF statement, wouldn't it return 'true' when the querySelector returns true and thus the promise is resolved...

HOWEVER, that is opposite of what I'm seeing. When calling the disappear method, the method does actually return when the element is no longer part of the dom... I'm just 100% confused WHY it does b/c the if statement logic suggests that it wouldn't...

TallKU
  • 179
  • 12
  • Can only resolve a promise once which may be part of your issue. So when you call these functions becomes important. Provide a *runnable* example that demonstrates what you are seeing – charlietfl Aug 09 '19 at 20:05
  • "*Doesn't it return null if the element wasn't found in the DOM?*" - yes. "*when the querySelector returns true and thus the promise is resolved*" - I'm not sure what you mean by "return true" here as there are no booleans returned anywhere, but when `querySelector` does find and return a value that is truthy and so the function `return`s prematurely without resolving - it only stops the interval and fulfills the promise when `querySelector` returns `null`. – Bergi Aug 09 '19 at 21:10
  • Have you considered a [Custom event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events) rather than a promise here? Or as Damien mentions below. Mutation Observer. – Bibberty Aug 09 '19 at 21:16

1 Answers1

1

The return statement happens within the function given to setInterval, it is not directly part of the elementVisibilityWatcherAppear function. If the function given to setInterval returns, nothing special happens until the function is called again. The interesting part happens in the other case: then the function stops being called and the promise returns with resolve().

By the way, you might be interested in using MutationObserver.

Damien
  • 3,060
  • 1
  • 25
  • 29
  • So, I'm using this function within #TestCafe to 'wait' until this DOM element created or destroyed within the DOM... So, I don't think 'MutationObserver' would be the best option. Plain an simple, if the ID/class that I'm waiting to location (aka #progress-bar) is present - wait until it is NOT present. If the ID/class (aka #side-bar) is NOT present but will appear shortly, wait until it is there. If there is a better code that needs to be generated for this, I'm all for refactoring. – TallKU Aug 12 '19 at 15:23
  • as an FYI - I found the original code from: https://stackoverflow.com/questions/54970442/how-to-wait-for-an-element-to-disappear-in-testcafe – TallKU Aug 12 '19 at 16:06