2016-01-06 23 views
5

A previous question revealed how to load in jQuery using native JavaScript. che ho usato con successo il codice di richiamata dalla risposta c'è, replicati qui:carico con JavaScript utilizzando 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... 
    }); 
})(); 

Come posso ottenere lo stesso risultato utilizzando native JavaScript Promises?

La ragione Chiedo è perché improvvisamente ho bisogno di ricomporre il callback precedente, ed è un pasticcio. Spero che le Promesse siano un modo migliore e non ho alcun reale interesse nell'utilizzo di un framework di caricamento.

Ecco quello che ho finora, ma la promessa finisce sempre respinto: (. Mi dispiace in anticipo per la mia completa ignoranza)

// 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

È necessario continuare a utilizzare il vecchio codice e solo a risolvere la promessa quando jquery è pronto. In questo caso non è necessario rifiutarlo, a meno che jquery non si carichi dopo un periodo di tempo. –

risposta

5

Ecco una versione che rende una semplice funzione loadScript() che restituisce una promessa e poi fornisce un wrapper attorno ad esso che rileva se jQuery è già caricato:

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 
}); 

note sul codice:

  1. Nel tuo primo blocco di codice, impostando un singolo timer e assumendo che lo script verrà caricato quando il timer scatta è come giocare alla roulette. Potrebbe funzionare la maggior parte del tempo, ma non è un metodo puramente affidabile per fare le cose. Inoltre, per sicurezza, è necessario impostare il timer su un periodo di tempo più lungo di quanto sia normalmente necessario. Invece, è necessario eseguire l'attivazione in base al callback onload dello script. Allora saprai esattamente quando lo script è pronto con il 100% di affidabilità.

  2. Nel secondo blocco di codice, la versione di promessa gestisce correttamente il caso in cui jQuery è già caricato, ma poi rejects() quando jQuery deve essere caricato su misura. Come puoi vedere dal mio esempio, è necessario resolve() quando il tag script appena caricato ha terminato il caricamento per far sì che la tua promessa funzioni come desiderato.

+0

Molto utile, in particolare con la funzione astratta 'loadScript()' nel caso in cui avessi bisogno di trascinare altri script in futuro! E grazie per le note sul codice esistente - ho sicuramente avuto barriere nelle mie conoscenze in quelle aree. – Rydash

0

script inseriti nella pagina in questo modo vengono eseguiti in modo asincrono. (Vedere "Dynamically importing scripts" su MDN.) Di conseguenza, window.jQuery sarà sempre undefined.

Provare ad allegare un gestore onload all'elemento di script in modo tale che la risoluzione della Promessa venga eseguita solo dopo che lo script è stato eseguito.

Per esempio (prima di impostare script.src):

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

Come al solito, questo metodo non è compatibile con tutti i browser. Controlla this post out per i modi per sistemarli.

0

Il problema è che questo è un asincrono modo non bloccante per caricare javascript. Dovrai aspettare che il browser scarichi lo script.

Questa è una possibile soluzione:

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"); 
     } 
    }); 
});