dynamisk - Javascript onload-händelse - hur kan man avgöra om skriptet redan är laddat?


Hur kan jag använda JavaScript för att avgöra om ett HTMLScriptElement redan har laddats helt?

Hur kan jag avgöra om ett dynamiskt laddat skript har slutat laddas utan att använda onload- eller onreadystatechange-händelserna?

Koden är som följer:

   TOOL.loadScript = function (url, callback, reappend, deepSearch) {
      var head, curr, child, tempScript, alreadyAppended, queue, 
      alreadyHandled, script, handler, loadFunc; 

      head = document.getElementsByTagName("head")[0];
      tempScript = document.createElement("script");
      tempScript.src = url;
      alreadyAppended = false;

      queue = []; 

      if (deepSearch) {
         // search entire document
         queue.push(document.firstElementChild);
      }
      else { 
         // just search the head element
         queue.push(head); 
      }

      while (queue.length !== 0) { 
         curr = queue.shift();

         // add child nodes to queue
         child = curr.firstElementChild; 
         if (child !== null && child !== undefined) { 
            queue.push(child);
            child = child.nextElementSibling;
            while (child !== null && child !== undefined) { 
               queue.push(child);
               child = child.nextElementSibling;
            } 
         }

         if (curr.tagName !== null && curr.tagName !== undefined) {
            if (curr.tagName.toLowerCase() === "script" && curr.src === tempScript.src) {
               script = curr;
               alreadyAppended = true;
               break;
            }
         }
      }

      if (!alreadyAppended) { 
         script = document.createElement("script");
         script.type = "text/javascript"; 
         script.async = true; 
         script.src = url; 
      } 

      alreadyHandled = false; 

      handler = function (event) {
         console.log("handling event..."); 
         if (!alreadyHandled) { 
            if ((!event.readyState) || (event && (event.readyState === "loaded" || event.readyState === "complete"))) {  
               alreadyHandled = true; 
               callback.apply(script, [url]);
               if (loadFunc) { 
                  loadFunc.apply(script, arguments); 
               }
            }
         }
      }; 

      if (script.onreadystatechange === undefined) { 
         loadFunc = script.onload;
         script.onload = handler; 
      } 
      else { 
         loadFunc = script.onreadystatechange; 
         script.onreadystatechange = handler; 
      } 

Jag behöver hjälp här. Jag vill att callback-funktionen ska köras även om alreadyAppeneded === true och samma skript redan har laddats, men endast om det skriptet är helt klart med att laddas.

      if (!alreadyAppended || (alreadyAppended && reappend)) { 
         head.appendChild(script); 
      } 
   };

SLUTSATS: Hur kan jag avgöra om ett skript har laddats klart? Vänligen ställ frågor om det behövs.

Tack.

Svar #1

Varför inte lägga till ett id på script-elementet? Kontrollera om id:t finns innan du fortsätter....

function includeJs(jsFilePath) {

  if (document.getElementById(jsFilePath+"_script")) {
    return;
  }
  var js = document.createElement("script");

  js.type = "text/javascript";
  js.id = jsFilePath+"_script";
  js.src = jsFilePath;

  document.body.appendChild(js); 
}

Svar #2

Lat implementering: Skapa en array som du kan använda för att lägga till källan till alla inladdade skript, och när de laddas, lägg dem på listan. Varje gång, kontrollera om den angivna src finns i arrayen, och om den gör det, kör callbacken omedelbart.

Vad du gör med fallet när det är bifogat, men inte laddat blir frågan. Om du vill att callbacken ska köras, men du vill att den ska köras efter att den laddas, kan du göra en associativ array med en src som nyckel och skriptelementet som värde. Därifrån, låt onload eller onreadystatechange köras två gånger genom att omsluta originalet, på följande sätt:

var temponload = element.onreadystatechange || element.onload;
if (element.onreadystatechange === undefined)
    element.onload = function(e) { temponload(); temponload(); };
else
    element.onreadystatechange = function (e) { temponload(); temponload(); };

Du har annan kod som kanske behöver kopplas in i detta, men detta borde förhoppningsvis få dig igång.