2016-01-06 4 views
5

A previous question revealed how to load in jQuery using native JavaScript. Mam powodzeniem stosowane kod oddzwonienia z odpowiedzi tam, replikowane tutaj:obciążenia z wykorzystaniem JavaScript Promises

// Anonymous "self-invoking" function 
(function() { 
    // Load the script 
    var script = document.createElement("SCRIPT"); 
    script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js'; 
    script.type = 'text/javascript'; 
    document.getElementsByTagName("head")[0].appendChild(script); 

    // Poll for jQuery to come into existance 
    var checkReady = function(callback) { 
     if (window.jQuery) { 
      callback(jQuery); 
     } 
     else { 
      window.setTimeout(function() { checkReady(callback); }, 100); 
     } 
    }; 

    // Start polling... 
    checkReady(function($) { 
     // Use $ here... 
    }); 
})(); 

Jak mogę osiągnąć to samo przy użyciu native JavaScript Promises?

Powód Pytam, ponieważ nagle potrzebuję odciąć się od wcześniejszego oddzwaniania i jest to cholerny bałagan. Mam nadzieję, że obietnice są lepszym sposobem i nie mam żadnego rzeczywistego zainteresowania używaniem platformy ładującej.

Oto co mam do tej pory, ale obietnica zawsze kończy się odrzucone: (. Przepraszam z góry za mój pełny ignorancji)

// This code doesn't work quite right. 
// Poll for jQuery to come into existance using a Promise 
var jQueryReady = new Promise(
    function(resolve, reject) { 

     // Load jQuery 
     var script = document.createElement('SCRIPT'); 
     script.type = 'text/javascript'; 
     script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'; 
     document.getElementsByTagName('head')[0].appendChild(script); 

     if (window.jQuery) { 
     resolve("YAY"); 
     } else { 
     reject("UGH"); 
     } 
    }); 

jQueryReady.then(
    function(success) { 
    console.log(success); 
    }, 
    function(error) { 
    console.error("Really helpful error:", error); 
    }); 

+0

Powinieneś kontynuować używanie starego kodu i tylko rozwiązać obietnicę, gdy jquery jest gotowy. Nie ma potrzeby odrzucania go w tym przypadku, chyba że jquery nie załaduje się po pewnym czasie. –

Odpowiedz

5

Oto wersja sprawia, że ​​prosty loadScript() funkcję zwracającą obietnicę a następnie udostępnia owijkę wokół niego, który wykrywa czy jQuery jest już załadowany:

function loadScript(url) { 
    return new Promise(function(resolve reject) { 
     var script = document.createElement("script"); 
     script.onload = resolve; 
     script.onerror = reject; 
     script.src = url; 
     document.getElementsByTagName("head")[0].appendChild(script); 
    }); 
} 

function loadjQuery() { 
    if (window.jQuery) { 
     // already loaded and ready to go 
     return Promise.resolve(); 
    } else { 
     return loadScript('https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'); 
    } 
} 


// Usage: 
loadjQuery().then(function() { 
    // code here that uses jQuery 
}, function() { 
    // error loading jQuery 
}); 

Uwagi o kodzie:

  1. W pierwszym bloku kodu ustawienie pojedynczego timera i założenie, że skrypt zostanie załadowany po uruchomieniu tego timera, jest jak gra w ruletkę. To może działać przez większość czasu, ale nie jest to czysto niezawodna metoda robienia rzeczy. Ponadto, aby być bezpiecznym, musisz ustawić timer na dłuższy czas, niż zwykle jest to konieczne. Zamiast tego należy wywoływać na podstawie wywołania zwrotnego skryptu onload. Wtedy będziesz dokładnie wiedzieć, kiedy skrypt jest gotowy ze 100% niezawodnością.

  2. W drugim bloku kodu wersja obietnica pomyślnie obsługuje przypadek, w którym jQuery jest już załadowany, ale następnie rejects(), gdy jQuery musi być załadowany niestandardowo. Jak możesz zobaczyć na moim przykładzie, musisz mieć resolve(), kiedy załadowany ostatnio znacznik skryptu zakończy ładowanie, aby Twoja obietnica działała zgodnie z oczekiwaniami.

+0

Bardzo przydatne, szczególnie w przypadku funkcji abstrakcji 'loadScript()' na wypadek, gdyby w przyszłości musiałem pobrać inne skrypty! I dziękuję za uwagi na temat istniejącego kodu - na pewno w tych obszarach miałem przepaście. – Rydash

0

Skrypty wstawiony na stronę w ten sposób są wykonywane asynchronicznie. (Zobacz "Dynamically importing scripts" na MDN.) W rezultacie window.jQuery zawsze będzie undefined.

Spróbuj przypiąć do elementu skryptu obsługę onload, tak aby rozdzielczość Promise była wykonywana tylko po wykonaniu skryptu.

Na przykład (przed ustawieniem script.src):

script.onload = function() { 
    if (window.jQuery) { 
     resolve("YAY"); 
    } else { 
     reject("UGH"); 
    } 
}; 

Jak zwykle, ta metoda nie jest kompatybilny ze wszystkimi przeglądarkami. Sprawdź this post out pod kątem sposobów ich dostosowania.

0

Problem polega na tym, że jest to nieblokujący sposób ładowania javascript. Będziesz musiał poczekać, aż przeglądarka pobierze skrypt.

Jest to możliwe rozwiązanie:

var jQueryReady = new Promise(
    function(resolve, reject) { 

    // Load jQuery 
    var script = document.createElement('SCRIPT'); 
    script.type = 'text/javascript'; 
    script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'; 
    document.getElementsByTagName('head')[0].appendChild(script); 

    // You should also have a timeout in case your script never loads 
    var timeoutHandler = setTimeout(10000, function() { 
     if (checkIntervalHandler) clearInterval(checkIntervalHandler); 
     reject("UGH"); 
    }); 

    var checkIntervalHandler = setInterval(500, function() { 
     if (window.jQuery) { 
     if(timeoutHandler) clearTimeout(timeoutHandler); 
     resolve("YAY"); 
     } 
    }); 
});