Klasa ładowana ansynchronicznie - zewnętrzny resource

0
<script type="text/javascript" src="https://static.example.com/script.min.js"></script>
<script type="text/javascript">
var myClass = new MyClass({
    selector: '.page-class'
});

Mam takie coś jak wyżej i działa to prawidłowo. Chciałbym jednak to przepisać na wersje podobną jak stosuje GA i inne podobne. Chodzi o asynchroniczność, ale też względy praktyczne - łatwiej instalować taki skrypt w CMSach gdzie czasami można wkleić tylko kod JS bez znaczników script.

<script type="text/javascript">
(function() {
    var sc = document.createElement('script'); sc.async = true; sc.type = 'text/javascript';
    sc.src = 'https://static.example.com/script.min.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(sc, s);
})();

// nie mam dostępu do klasy

To czemu nie mam dostępu - mniej więcej dla mnie jest zrozumiałe, tylko pytanie czy jestem w stanie to obejść? Oczywiście dostęp i możliwość zmiany czegoś w script.js mam.

0
s.onload = function() {
  // tutaj powinieneś mieć dostęp do klasy
};
0

Niestety nie działa.

MyClass is not defined

Może ma wpływ na to jak sam plik z klasą wygląda?

(function() {
    var MyClass= function(opts){
        window.addEventListener('DOMContentLoaded', () => {
            // atrybuty, config itp
            init(this);
        })
    };

   // inne metody
0

Deklarujesz zmienną lokalną - siłą rzeczy nie będzie widoczna poza tą funkcją.

0

Zapomniałem o najważniejszym, na końcu jest

window.MyClass = MyClass;

Tak jak pisałem na początku, przy wersji z ładowaniem script przez url działa wszystko bez problemu.

0

@up

0

Jeżeli nie masz zupełnie kontroli nad tym wstrzykiwanym kodem ale wiesz, że definiuje on finalnie window.MyClass to możesz zrobić jakiś interval który będzie sprawdzał co X milisekund czy ten obiekt istnieje, jeżeli tak to dopiero wykona na nim jakiś kod - nie jest to dobre rozwiązanie, lepiej się podpiąć pod onload jak wspominał kolega wyżej albo coś takiego.

setInterval(() => {
   if (window.hasOwnProperty('MyClass')) {
      console.log('Już mam dostęp do MyClass');
   }
}, 100);

ew. możesz wykorzystać MutationObserver, chociaż nie jestem pewny czy nasłuchiwanie na całe window nie zrobi zamieszania.

Edit. jak masz dostęp do zrób to co napisał @Patryk27 tj.

<script type="text/javascript">
(function() {
    var sc = document.createElement('script'); sc.async = true; sc.type = 'text/javascript';
    sc.src = 'https://static.example.com/script.min.js';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(sc, s);
    sc.onload = function() {
       console.log('Już mam dostęp do MyClass (chyba, że ten script wygląda jakoś dziwnie, wtedy nie mam ;)');
    }
})();
</sciprt>
0

Daje "cały" kod klasy (zawartość pliku js).

(function() {
    var MyClass= function(opts){
        window.addEventListener('DOMContentLoaded', () => {
            // atrybuty, config itp
            init(this);
        })
    };

    window.MyClass = MyClass;

});

Próba wywołania tej klasy na innej stronie jest pokazana na początku tematu.

0
function initClass(Cls) {
    var myClass = new Cls({
        selector: '.page-class'
    });
}


(function() {
    var sc = document.createElement('script'); sc.async = true; sc.type = 'text/javascript';
    sc.src = 'https://static.example.com/script.min.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(sc, s);

    sc.addEventListener('load', () => { initClass(window.MyClass)})
})();

Tylko zdajesz sobie sprawę, że to:

window.addEventListener('DOMContentLoaded', () => {
            // atrybuty, config itp
            init(this);
        })

Prawdopodobnie nigdy się nie odpali. Kiedy skrypt z klasą zdąży się ściągnąć i sparsować to event DOMContentLoaded już dawno został wyemitowany.

0

Oki, podaje przykłady na żywo:

Wersja w load działa ale przekazuje "pusty obiekt" (patrz konsola):
http://ebizo.pl/temp/file.html

A tu wersja z normalnym script src:
http://ebizo.pl/temp/file2.html

0
eBizo napisał(a):

Oki, podaje przykłady na żywo:

Wersja w load działa ale przekazuje "pusty obiekt" (patrz konsola):
http://ebizo.pl/temp/file.html

A tu wersja z normalnym script src:
http://ebizo.pl/temp/file2.html

Wywal DOMContentLoaded, przecież twój skrypt ściągnie się już PO tym jak DOMContentLoaded został wyemitowany. Dlatego funkcje z klasy nigdy się nie wywołują

(function(){

    var MyClass = function(opts){
            this.options        = [1, 2];
            console.log('TURN ON');
    };

    // make accessible globally
    window.MyClass = MyClass;

})();

1 użytkowników online, w tym zalogowanych: 0, gości: 1