Removing setInterval

I would like to open this up and see if anyone is able to figure this out.

How would I remove setInterval from this code and for it to still work properly. I was told it’s not needed in the code, but I can’t figure out how to remove it and for the code to work the same as it did before.

Also, with the setInterval Code:

None of the YouTube stuff is cached in the browser until it is clicked.

It would need to work the same way as that too.

This is something I cannot figure out how to do.

Code:
https://jsfiddle.net/hzyrfkwb/63/ 1

let apiIsReady = false;
let timer;
window.onYouTubePlayerAPIReady = function() {
    apiIsReady = true;
};

function init(opts) {
    loadPlayer();
    timer = setInterval(function checkAPIReady() {
        if (apiIsReady) {
            timer = clearInterval(timer);
            addVideo(opts.video, opts.playerVars || {});
        }
    }, 100);
}
return {
    init
};
}());

Full Code:


const videoPlayer = (function makeVideoPlayer() {
    "use strict";
    const players = [];

    function loadPlayer() {
        const tag = document.createElement("script");
        tag.src = "https://www.youtube.com/player_api";
        const firstScriptTag = document.getElementsByTagName("script")[0];
        firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
    }

    function onPlayerReady(event) {
        const player = event.target;
        player.setVolume(50); // percent
    }

    function onPlayerStateChange(event) {
        const player = event.target;
        if (event.data === YT.PlayerState.PLAYING) {
            const otherVideos = (video) => video !== player;
            const pauseVideo = (video) => video.pauseVideo();
            players.filter(otherVideos).forEach(pauseVideo);
        }
        const playerVars = player.b.b.playerVars;
        if (playerVars.loop && event.data === YT.PlayerState.ENDED) {
            player.seekTo(playerVars.start);
        }
    }

    function addVideo(video, desiredPlayerVars) {
        const videoId = video.getAttribute("data-id");
        const defaultPlayerVars = {
            autoplay: 1,
            controls: 1,
            showinfo: 1,
            rel: 0,
            iv_load_policy: 3,
            cc_load_policy: 0,
            fs: 0,
            disablekb: 1
        };
        const playerVars = Object.assign(defaultPlayerVars, desiredPlayerVars);
        players.push(new YT.Player(video, {
            width: 200,
            height: 200,
            videoId: videoId,
            // defaultPlayerVars,
            playerVars,
            events: {
                "onReady": onPlayerReady,
                "onStateChange": onPlayerStateChange
            }
        }));
    }
    let apiIsReady = false;
    let timer;
    window.onYouTubePlayerAPIReady = function() {
        apiIsReady = true;
    };
    function init(opts) {
        loadPlayer();
        timer = setInterval(function checkAPIReady() {
            if (apiIsReady) {
                timer = clearInterval(timer);
                addVideo(opts.video, opts.playerVars || {});
            }
        }, 100);
    }
    return {
        init
    };
}());
(function iife() {
    "use strict";
    const show = (el) => el.classList.remove("hide");

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        videoPlayer.init({
            video: wrapper.querySelector(".video"),
            playerVars: {
                start: 900,
                end: 1200
            }
        });
    }
    const cover = document.querySelector(".playa");
    cover.addEventListener("click", coverClickHandler);
}());
(function iife() {
    "use strict";
    const show = (el) => el.classList.remove("hide");

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        videoPlayer.init({
            video: wrapper.querySelector(".video"),
            playerVars: {
                start: 30,
                end: 50
            }
        });
    }
    const cover = document.querySelector(".playb");
    cover.addEventListener("click", coverClickHandler);
}());
(function iife() {
    "use strict";
    const show = (el) => el.classList.remove("hide");

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        videoPlayer.init({
            video: wrapper.querySelector(".video"),
            playerVars: {
                start: 30,
                end: 50
            }
        });
    }
    const cover = document.querySelector(".playc");
    cover.addEventListener("click", coverClickHandler);
}());
(function iife() {
    "use strict";
    const show = (el) => el.classList.remove("hide");

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        videoPlayer.init({
            video: wrapper.querySelector(".video"),
            playerVars: {
                start: 30,
                end: 50
            }
        });
    }
    const cover = document.querySelector(".playd");
    cover.addEventListener("click", coverClickHandler);
}());
(function iife() {
    "use strict";
    const show = (el) => el.classList.remove("hide");

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        videoPlayer.init({
            video: wrapper.querySelector(".video"),
            playerVars: {
                start: 30,
                end: 50
            }
        });
    }
    const cover = document.querySelector(".playe");
    cover.addEventListener("click", coverClickHandler);
}());
(function iife() {
    "use strict";
    const show = (el) => el.classList.remove("hide");

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        videoPlayer.init({
            video: wrapper.querySelector(".video"),
            playerVars: {
                start: 30,
                end: 50
            }
        });
    }
    const cover = document.querySelector(".playf");
    cover.addEventListener("click", coverClickHandler);
}());
(function iife() {
    "use strict";
    const show = (el) => el.classList.remove("hide");

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        videoPlayer.init({
            video: wrapper.querySelector(".video"),
            playerVars: {
                start: 30,
                end: 50
            }
        });
    }
    const cover = document.querySelector(".playg");
    cover.addEventListener("click", coverClickHandler);
}());
(function iife() {
    "use strict";
    const show = (el) => el.classList.remove("hide");

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        videoPlayer.init({
            video: wrapper.querySelector(".video"),
            playerVars: {
                start: 30,
                end: 50
            }
        });
    }
    const cover = document.querySelector(".playh");
    cover.addEventListener("click", coverClickHandler);
}());
(function iife() {
    "use strict";
    const show = (el) => el.classList.remove("hide");

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        videoPlayer.init({
            video: wrapper.querySelector(".video"),
            playerVars: {
                start: 30,
                end: 50
            }
        });
    }
    const cover = document.querySelector(".playi");
    cover.addEventListener("click", coverClickHandler);
}());

Who told you that, and where? What approach did they suggest?

I was suggested to use this:

But this didn’t work.

And then he said the code seemed complicated.

let apiIsReady = false;
let timer;
window.onYouTubePlayerAPIReady = function() {
    apiIsReady = true;
    init(); // this.init();
};

function init(opts) {
    loadPlayer();
    addVideo(opts.video, opts.playerVars || {});
}
return {
    init
};

Who suggested it, and where? Please link to the discussion, so that others trying to assist have the full picture.

You have already discussed this issue in your other topic:

That doesn’t seem to be what you’re referring to here.

That was me that said that’s how it would be done without the setInterval.
I don’t recall saying that it would work in any way. Just that it would achieve his desire to remove setInterval.

Critique of the code is welcomed. If anyone has ideas on how to improve it, then by all means bring forth the suggestions.
I for one would remove a lot of duplication that’s in there, but that’s just me.

1 Like

Thanks, Paul.

Can the other topic be closed now, to prevent further confusion from cross-posting?

I’m good with that, so long as we can get a suitable renaming of this thread to represent the broader scope of things.

I’ll now sit back (beddy-byes) for about 8 hours to let people work their magic here. :slight_smile:

2 Likes

No, it was actually on Stack Overflow.

My contribution towards your question was also at

G’Night all. :zzz:

3 Likes

In which case, once again, please provide the link.

2 Likes

I deleted the post because it got -10 on my question I asked on there.

I didn’t want it to keep going to -20.

I was able to screen capture it.

image

1 Like

Okay, I can’t sleep.

Is it enough to load the player when the page first loads, by moving it below the init function?

    function init(opts) {
      addVideo(opts.video, opts.playerVars || {});
    }
    loadPlayer();
    return {
        init
    };
1 Like

Is one way right, and the other wrong?

Is
loadPlayer();
supposed to be under
function init(opts) { ?

Would there be more to improve?

It works like this:

 };
    function init(opts) {
      addVideo(opts.video, opts.playerVars || {});
    }
     loadPlayer();
    return {
        init
    };
}());

It doesn’t work like this:

  };
    function init(opts) {
     loadPlayer();
      addVideo(opts.video, opts.playerVars || {});
    }
    return {
        init
    };
}());

So close, you almost got it.
Maybe something would need to be adjusted in one of those two codes.

It would need to work like this:

Good
The api doesn’t load in this one:
But the player doesn’t work like this.

  };
    function init(opts) {
     loadPlayer();
      addVideo(opts.video, opts.playerVars || {});
    }
    return {
        init
    };
}());

VS.

Bad
The api loads in this one:
But the player is functional here.

 };
    function init(opts) {
      addVideo(opts.video, opts.playerVars || {});
    }
     loadPlayer();
    return {
        init
    };
}());

Updated Text:

It would need to work like this:

Good
The api doesn’t load in this one:
But the player doesn’t work like this.
It does, it just takes 2 Clicks for the video to appear instead of 1 Click.

  };
    function init(opts) {
     loadPlayer();
      addVideo(opts.video, opts.playerVars || {});
    }
    return {
        init
    };
}());

When loadPlayer is inside the init function, what’s preventing the video from being shown after 1 Click, instead of 2 Clicks? And is there any way to resolve, fix that issue, while keeping loadPlayer inside the init function?

 };
    function init(opts) {
     loadPlayer();
      addVideo(opts.video, opts.playerVars || {});
    }
    return {
        init
    };
}());

No there’s not.

When the first click happens, loadPlayer occurs and the youtube api is being downloaded. That code doesn’t get to be run and made active for some time (100 to 500 milliseconds).
While that api is being downloaded, addVideo then runs. the addVideo function uses YT which doesn’t exist yet. That comes from the api, and cannot add the video. When that code finishes, the downloading of the api continues, and when that is complete the api runs, making YT and the youtube api available to us.

That’s what happens with the first click.

With the second click that all happens again. loadPlayer attempts to download the api, but it’s already downloaded from last time, which doesn’t seem to be a problem because downloading the youtube api multiple times when it should be only once, doesn’t seem strange to you. The addVideo code then runs, and because YT is available from the api from last time, that can now work to add the video, and start downloading the video and playing it.

When the youtube api is being loaded, that takes time to load. There’s no getting around that.
If you want to load the api and then use it, you must wait for it to get here before using it.

Currently you want to delay getting the youtube API until someone clicks on a video. Have you a good reason for that delay? Because that requires setInterval.

Have you a good reason to not get the youtube API first. Getting the api first (by using loadPlayer outside of the init function) while waiting for someone to click on a video to play, is the simpler and more reliable solution.

1 Like

That seems to be the only way to do things without using setInterval

What’s wrong with the api loading?

It takes time for the API to load., It physically doesn’t exist when addVideo runs.
What prevents that from working is that’s how browsers work. Time travel is strictly against the rules.

1 Like

I would like to get your opinion of this way of doing it:

I think it’s bad, and a terrible way to do it.

What do you think?

It might give you some ideas on a different way of doing it.