0

I wrote a content script to run inside YouTube:

let id = '';
while (true) {
    let newId = await getVideoId(true);
    if (newId && newId !== id) {
        console.log('New id', newId);
        await handleVideo();
        id = newId;
    }
    await pause(50);
}

Whenever the user visits another video, handleVideo interacts with the DOM elements. Internally, handleVideo uses myQuerySelector that follows to get an element as soon as it is available:

function pause(delay) {
    return new Promise((resolve) => setTimeout(resolve, delay));
}

// Wait for at most maxDelay time
async function myQuerySelector(selector, all = false, maxDelay = 10000) {
    const delay = 50; //ms
    let totalDelay = 0;
    let elements = [];
    while (totalDelay <= maxDelay) {
        elements = Array.from(document.querySelectorAll(selector))
        if (elements.length) break;
        await pause(delay);
        totalDelay += delay;
    }
    console.log(`Found after ${totalDelay}`, selector)
    return all ? elements : elements[0];
}

The difficulty I am facing is that when I visit a new video, the elements are available right away, but the content I am getting from those elements is the content from the previous video. How do I make sure that the elements have been updated?

P.S. The strangest thing is that this happens even when the user visits the channel page between the two videos. How do the elements persist in this case?

AlwaysLearning
  • 7,257
  • 4
  • 33
  • 68
  • Afaik, YouTube is a SPA (single page application). There only is one page. When you "navigate", JS on the page just rewrites the page with the new content. – Carcigenicate Jul 30 '23 at 15:31
  • @Carcigenicate So what can I do to make sure that I am getting the content pertaining to the current video? – AlwaysLearning Jul 30 '23 at 15:34
  • You could find an event that gets fired on navigation, and set up an event listener on it to re-run your code when that event is fired. – Carcigenicate Jul 30 '23 at 15:35
  • @Carcigenicate What navigation are you referring to? I already catch navigating to another video... – AlwaysLearning Jul 30 '23 at 15:37
  • It means you catch it too early. See [this example](/a/34100952) or use MutationObserver to detect the change in an element instead of setTimeout. – wOxxOm Jul 30 '23 at 15:50
  • @AlwaysLearning Did you try to listen the url change. Because when video changes URL changes as well. [Listen URL change on content script inside Chrome Extension](https://stackoverflow.com/a/50548409/9969193) – SeLeCtRa Jul 30 '23 at 19:15
  • @SeLeCtRa How is listening to URL change better than what my code is doing? – AlwaysLearning Jul 30 '23 at 19:51
  • @wOxxOm I substituted the call to `handleVideo` with `document.addEventListener('yt-navigate-finish', handleVideo);` but still observe the same behavior... – AlwaysLearning Jul 30 '23 at 20:07

0 Answers0