file função - Como faço para incluir um arquivo JavaScript em outro arquivo JavaScript?




chamar from (25)

Aqui está a versão generalizada de como o Facebook faz isso por seu onipresente botão Like:

<script>
  var firstScript = document.getElementsByTagName('script')[0],
      js = document.createElement('script');
  js.src = 'https://cdnjs.cloudflare.com/ajax/libs/Snowstorm/20131208/snowstorm-min.js';
  js.onload = function () {
    // do stuff with your dynamically loaded script
    snowStorm.snowColor = '#99ccff';
  };
  firstScript.parentNode.insertBefore(js, firstScript);
</script>

Se funcionar para o Facebook, funcionará para você.

A razão pela qual procuramos o primeiro elemento de script vez de head ou body é porque alguns navegadores não criam um, se estiverem faltando, mas temos a garantia de ter um elemento de script - este. Leia mais em http://www.jspatterns.com/the-ridiculous-case-of-adding-a-script-element/ .

Existe algo em JavaScript semelhante ao @import em CSS que permite incluir um arquivo JavaScript dentro de outro arquivo JavaScript?


Há uma boa notícia para você. Muito em breve você poderá carregar o código JavaScript com facilidade. Ela se tornará uma maneira padrão de importar módulos de código JavaScript e fará parte do próprio JavaScript principal.

Você simplesmente tem que escrever import cond from 'cond.js'; para carregar uma macro nomeada cond de um arquivo cond.js

Portanto, você não precisa depender de nenhuma estrutura JavaScript nem de fazer explicitamente chamadas Ajax .

Referir-se:


Acabei de escrever este código JavaScript (usando Prototype para manipulação de DOM ):

var require = (function() {
    var _required = {};
    return (function(url, callback) {
        if (typeof url == 'object') {
            // We've (hopefully) got an array: time to chain!
            if (url.length > 1) {
                // Load the nth file as soon as everything up to the
                // n-1th one is done.
                require(url.slice(0, url.length - 1), function() {
                    require(url[url.length - 1], callback);
                });
            } else if (url.length == 1) {
                require(url[0], callback);
            }
            return;
        }
        if (typeof _required[url] == 'undefined') {
            // Haven't loaded this URL yet; gogogo!
            _required[url] = [];

            var script = new Element('script', {
                src: url,
                type: 'text/javascript'
            });
            script.observe('load', function() {
                console.log("script " + url + " loaded.");
                _required[url].each(function(cb) {
                    cb.call(); // TODO: does this execute in the right context?
                });
                _required[url] = true;
            });

            $$('head')[0].insert(script);
        } else if (typeof _required[url] == 'boolean') {
            // We already loaded the thing, so go ahead.
            if (callback) {
                callback.call();
            }
            return;
        }

        if (callback) {
            _required[url].push(callback);
        }
    });
})();

Uso:

<script src="prototype.js"></script>
<script src="require.js"></script>
<script>
    require(['foo.js','bar.js'], function () {
        /* Use foo.js and bar.js here */
    });
</script>

Gist: http://gist.github.com/284442 .


É possível gerar dinamicamente uma tag JavaScript e anexá-la ao documento HTML de outro código JavaScript. Isso carregará o arquivo JavaScript direcionado.

function includeJs(jsFilePath) {
    var js = document.createElement("script");

    js.type = "text/javascript";
    js.src = jsFilePath;

    document.body.appendChild(js);
}

includeJs("/path/to/some/file.js");

Eu criei uma função que permitirá que você use verbosidade semelhante ao C # / Java para incluir um arquivo JavaScript. Eu testei um pouco até de dentro de outro arquivo JavaScript e parece funcionar. Ele requer jQuery embora por um pouco de "magia" no final.

Eu coloquei este código em um arquivo na raiz do meu diretório de script (eu o nomeei global.js, mas você pode usar o que quiser. A menos que eu esteja enganado, o jQuery deve ser o único script necessário em uma determinada página. Lembre-se disso é em grande parte não testado além de algum uso básico, por isso pode ou não haver quaisquer problemas com a maneira que eu fiz isso, use a seu próprio risco yadda yadda Eu não sou responsável se você estragar tudo yadda yadda:

/**
* @fileoverview This file stores global functions that are required by other libraries.
*/

if (typeof(jQuery) === 'undefined') {
    throw 'jQuery is required.';
}

/** Defines the base script directory that all .js files are assumed to be organized under. */
var BASE_DIR = 'js/';

/**
* Loads the specified file, outputting it to the <head> HTMLElement.
*
* This method mimics the use of using in C# or import in Java, allowing
* JavaScript files to "load" other JavaScript files that they depend on
* using a familiar syntax.
*
* This method assumes all scripts are under a directory at the root and will
* append the .js file extension automatically.
*
* @param {string} file A file path to load using C#/Java "dot" syntax.
*
* Example Usage:
* imports('core.utils.extensions');
* This will output: <script type="text/javascript" src="/js/core/utils/extensions.js"></script>
*/
function imports(file) {
    var fileName = file.substr(file.lastIndexOf('.') + 1, file.length);

    // Convert PascalCase name to underscore_separated_name
    var regex = new RegExp(/([A-Z])/g);
    if (regex.test(fileName)) {
        var separated = fileName.replace(regex, ",$1").replace(',', '');
        fileName = separated.replace(/[,]/g, '_');
    }

    // Remove the original JavaScript file name to replace with underscore version
    file = file.substr(0, file.lastIndexOf('.'));

    // Convert the dot syntax to directory syntax to actually load the file
    if (file.indexOf('.') > 0) {
        file = file.replace(/[.]/g, '/');
    }

    var src = BASE_DIR + file + '/' + fileName.toLowerCase() + '.js';
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = src;

    $('head').find('script:last').append(script);
}

Isso deve fazer:

xhr = new XMLHttpRequest();
xhr.open("GET", "/soap/ajax/11.0/connection.js", false);
xhr.send();
eval(xhr.responseText);

As versões antigas do JavaScript não tinham importação, inclusão ou necessidade, portanto, muitas abordagens diferentes para esse problema foram desenvolvidas.

Mas desde 2015 (ES6), o JavaScript teve o padrão dos módulos ES6 para importar módulos no Node.js, que também é suportado pela maioria dos navegadores modernos .

Para compatibilidade com navegadores mais antigos, ferramentas de build e / ou transpilation podem ser usadas.

Módulos ES6

Módulos ECMAScript (ES6) foram suportados no Node.js desde a v8.5, com o --experimental-modules . Todos os arquivos envolvidos devem ter a extensão .mjs .

// module.mjs
export function hello() {
  return "Hello";
}
// main.mjs
import { hello } from 'module'; // or './module'
let val = hello();  // val is "Hello";

Módulos ECMAScript nos navegadores

Os navegadores têm suporte para o carregamento de módulos ECMAScript diretamente (sem necessidade de ferramentas como o Webpack) since Safari 10.1, Chrome 61, Firefox 60 e Edge 16. Verifique o suporte atual em caniuse .

<script type="module">
  import { hello } from './hello.mjs';
  hello('world');
</script>
// hello.mjs
export function hello(text) {
  const div = document.createElement('div');
  div.textContent = `Hello ${text}`;
  document.body.appendChild(div);
}

Leia mais em: since

Importações dinâmicas em navegadores

As importações dinâmicas permitem que o script carregue outros scripts conforme necessário:

<script type="module">
  import('hello.mjs').then(module => {
      module.hello('world');
    });
</script>

Leia mais em: https://developers.google.com/web/updates/2017/11/dynamic-import

Node.js requer

O estilo antigo de importar módulos, ainda amplamente usado no Node.js, é o module.exports/require .

// mymodule.js
module.exports = {
   hello: function() {
      return "Hello";
   }
}
// server.js
const myModule = require('./mymodule');
let val = myModule.hello(); // val is "Hello"   

Existem outras maneiras de o JavaScript incluir conteúdo JavaScript externo em navegadores que não exigem pré-processamento.

AJAX Carregando

Você poderia carregar um script adicional com uma chamada AJAX e, em seguida, usar o eval para executá-lo. Essa é a maneira mais direta, mas é limitada ao seu domínio por causa do modelo de segurança do sandbox do JavaScript. O uso do eval também abre as portas para bugs, hacks e problemas de segurança.

jQuery Loading

A biblioteca jQuery fornece funcionalidade de carregamento em uma linha :

$.getScript("my_lovely_script.js", function() {
   alert("Script loaded but not necessarily executed.");
});

Carregamento de script dinâmico

Você pode adicionar uma tag de script com o URL do script no HTML. Para evitar a sobrecarga do jQuery, esta é uma solução ideal.

O script pode até residir em um servidor diferente. Além disso, o navegador avalia o código. A tag <script> pode ser injetada na tag da web <head> ou inserida logo antes da tag de fechamento </body> .

Aqui está um exemplo de como isso poderia funcionar:

function dynamicallyLoadScript(url) {
    var script = document.createElement("script");  // create a script DOM node
    script.src = url;  // set its src to the provided URL

    document.head.appendChild(script);  // add it to the end of the head section of the page (could change 'head' to 'body' to add it to the end of the body section instead)
}

Essa função adicionará uma nova tag <script> ao final da seção head da página, onde o atributo src é definido para a URL que é dada à função como o primeiro parâmetro.

Ambas as soluções são discutidas e ilustradas em JavaScript Madness: Dynamic Script Loading .

Detectando quando o script foi executado

Agora, há um grande problema que você deve conhecer. Isso implica que você carregue remotamente o código . Os navegadores da Web modernos carregam o arquivo e continuam executando seu script atual porque carregam tudo de forma assíncrona para melhorar o desempenho. (Isso se aplica tanto ao método jQuery quanto ao método de carregamento manual de script dinâmico.)

Isso significa que, se você usar esses truques diretamente, não poderá usar o código recém-carregado na próxima linha depois de solicitar que ele seja carregado , porque ele ainda estará sendo carregado.

Por exemplo: my_lovely_script.js contém MySuperObject :

var js = document.createElement("script");

js.type = "text/javascript";
js.src = jsFilePath;

document.body.appendChild(js);

var s = new MySuperObject();

Error : MySuperObject is undefined

Então você recarrega a página atingindo F5 . E isso funciona! Confuso ...

Então o que fazer sobre isso ?

Bem, você pode usar o hack que o autor sugere no link que eu te dei. Em resumo, para pessoas com pressa, ele usa um evento para executar uma função de retorno de chamada quando o script é carregado. Então você pode colocar todo o código usando a biblioteca remota na função de retorno de chamada. Por exemplo:

function loadScript(url, callback)
{
    // Adding the script tag to the head as suggested before
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;

    // Then bind the event to the callback function.
    // There are several events for cross browser compatibility.
    script.onreadystatechange = callback;
    script.onload = callback;

    // Fire the loading
    head.appendChild(script);
}

Então você escreve o código que você quer usar depois que o script é carregado em uma função lambda :

var myPrettyCode = function() {
   // Here, do whatever you want
};

Então você corre tudo isso:

loadScript("my_lovely_script.js", myPrettyCode);

Observe que o script pode ser executado depois que o DOM foi carregado ou antes, dependendo do navegador e se você incluiu a linha script.async = false; . Há um ótimo artigo sobre o carregamento de JavaScript em geral, que discute isso.

Mesclagem / pré-processamento de código-fonte

Como mencionado no início desta resposta, muitos desenvolvedores usam ferramentas de compilação / transpilação como Parcel, Webpack ou Babel em seus projetos, permitindo que usem a próxima sintaxe JavaScript, forneçam compatibilidade retroativa para navegadores mais antigos, combinem arquivos, minifiquem, executar o código de divisão etc.


Na linguagem moderna, seria

function loadJs( url ){
  return new Promise( resolve => {
    const script = document.createElement( "script" );
    script.src = url;
    script.onload = resolve;
    document.head.appendChild( script );
  });
}

Se alguém estiver procurando por algo mais avançado, experimente o RequireJS . Você obterá benefícios adicionais, como gerenciamento de dependência, melhor concorrência e evitar duplicação (ou seja, recuperar um script mais de uma vez).

Você pode escrever seus arquivos JavaScript em "módulos" e, em seguida, referenciá-los como dependências em outros scripts. Ou você pode usar o RequireJS como uma solução simples "vá buscar este script".

Exemplo:

Definir dependências como módulos:

some-dependency.js

define(['lib/dependency1', 'lib/dependency2'], function (d1, d2) {

     //Your actual script goes here.   
     //The dependent scripts will be fetched if necessary.

     return libraryObject;  //For example, jQuery object
});

implementation.js é o seu arquivo JavaScript "principal" que depende do some-dependency.js

require(['some-dependency'], function(dependency) {

    //Your script goes here
    //some-dependency.js is fetched.   
    //Then your script is executed
});

Trecho do README do GitHub :

O RequireJS carrega arquivos JavaScript simples, assim como módulos mais definidos. Ele é otimizado para uso no navegador, inclusive em um Web Worker, mas pode ser usado em outros ambientes JavaScript, como Rhino e Node. Implementa a API do módulo assíncrono.

O RequireJS usa tags de script simples para carregar módulos / arquivos, portanto, deve permitir uma depuração fácil. Ele pode ser usado simplesmente para carregar arquivos JavaScript existentes, para que você possa adicioná-lo ao seu projeto existente sem ter que reescrever seus arquivos JavaScript.

...


Eu escrevi um módulo simples que automatiza o trabalho de importar / incluir scripts de módulo em JavaScript. Para uma explicação detalhada do código, consulte a postagem do blog JavaScript require / import / include modules .

// ----- USAGE -----

require('ivar.util.string');
require('ivar.net.*');
require('ivar/util/array.js');
require('http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js');

ready(function(){
    //Do something when required scripts are loaded
});

    //--------------------

var _rmod = _rmod || {}; //Require module namespace
_rmod.LOADED = false;
_rmod.on_ready_fn_stack = [];
_rmod.libpath = '';
_rmod.imported = {};
_rmod.loading = {
    scripts: {},
    length: 0
};

_rmod.findScriptPath = function(script_name) {
    var script_elems = document.getElementsByTagName('script');
    for (var i = 0; i < script_elems.length; i++) {
        if (script_elems[i].src.endsWith(script_name)) {
            var href = window.location.href;
            href = href.substring(0, href.lastIndexOf('/'));
            var url = script_elems[i].src.substring(0, script_elems[i].length - script_name.length);
            return url.substring(href.length+1, url.length);
        }
    }
    return '';
};

_rmod.libpath = _rmod.findScriptPath('script.js'); //Path of your main script used to mark
                                                   //the root directory of your library, any library.


_rmod.injectScript = function(script_name, uri, callback, prepare) {

    if(!prepare)
        prepare(script_name, uri);

    var script_elem = document.createElement('script');
    script_elem.type = 'text/javascript';
    script_elem.title = script_name;
    script_elem.src = uri;
    script_elem.async = true;
    script_elem.defer = false;

    if(!callback)
        script_elem.onload = function() {
            callback(script_name, uri);
        };
    document.getElementsByTagName('head')[0].appendChild(script_elem);
};

_rmod.requirePrepare = function(script_name, uri) {
    _rmod.loading.scripts[script_name] = uri;
    _rmod.loading.length++;
};

_rmod.requireCallback = function(script_name, uri) {
    _rmod.loading.length--;
    delete _rmod.loading.scripts[script_name];
    _rmod.imported[script_name] = uri;

    if(_rmod.loading.length == 0)
        _rmod.onReady();
};

_rmod.onReady = function() {
    if (!_rmod.LOADED) {
        for (var i = 0; i < _rmod.on_ready_fn_stack.length; i++){
            _rmod.on_ready_fn_stack[i]();
        });
        _rmod.LOADED = true;
    }
};

_.rmod = namespaceToUri = function(script_name, url) {
    var np = script_name.split('.');
    if (np.getLast() === '*') {
        np.pop();
        np.push('_all');
    }

    if(!url)
        url = '';

    script_name = np.join('.');
    return  url + np.join('/')+'.js';
};

//You can rename based on your liking. I chose require, but it
//can be called include or anything else that is easy for you
//to remember or write, except "import", because it is reserved
//for future use.
var require = function(script_name) {
    var uri = '';
    if (script_name.indexOf('/') > -1) {
        uri = script_name;
        var lastSlash = uri.lastIndexOf('/');
        script_name = uri.substring(lastSlash+1, uri.length);
    } 
    else {
        uri = _rmod.namespaceToUri(script_name, ivar._private.libpath);
    }

    if (!_rmod.loading.scripts.hasOwnProperty(script_name)
     && !_rmod.imported.hasOwnProperty(script_name)) {
        _rmod.injectScript(script_name, uri,
            _rmod.requireCallback,
                _rmod.requirePrepare);
    }
};

var ready = function(fn) {
    _rmod.on_ready_fn_stack.push(fn);
};

Caso você esteja usando Web Workers e queira incluir scripts adicionais no escopo do worker, as outras respostas fornecidas sobre a adição de scripts à headtag, etc. não funcionarão para você.

Felizmente, os Web Workers têm sua própria importScriptsfunção, que é uma função global no escopo do Web Worker, nativa do próprio navegador, pois faz parte da especificação .

Como alternativa, como a segunda resposta mais votada para os destaques de sua pergunta , o RequireJS também pode manipular a inclusão de scripts dentro de um Web Worker (provavelmente chamando a importScriptssi mesmo, mas com alguns outros recursos úteis).


Na verdade, existe uma maneira de carregar um arquivo JavaScript não de forma assíncrona, para que você possa usar as funções incluídas em seu arquivo recém-carregado logo após carregá-lo, e acho que ele funciona em todos os navegadores.

Você precisa usar jQuery.append() no elemento <head> da sua página, ou seja:

$("head").append('<script type="text/javascript" src="' + script + '"></script>');

No entanto, esse método também tem um problema: se ocorrer um erro no arquivo JavaScript importado, o Firebug (e também o Firefox Error Console e as Chrome Developer Tools ) informará seu local incorretamente, o que é um grande problema se você usar o Firebug para rastrear Erros de JavaScript para baixo muito (eu faço). O Firebug simplesmente não sabe sobre o arquivo recém-carregado por algum motivo, portanto, se ocorrer um erro nesse arquivo, ele informará que ocorreu no arquivo HTML principal e você terá problemas para descobrir o motivo real do erro.

Mas se isso não é um problema para você, então este método deve funcionar.

Eu realmente escrevi um plugin jQuery chamado $ .import_js () que usa este método:

(function($)
{
    /*
     * $.import_js() helper (for JavaScript importing within JavaScript code).
     */
    var import_js_imported = [];

    $.extend(true,
    {
        import_js : function(script)
        {
            var found = false;
            for (var i = 0; i < import_js_imported.length; i++)
                if (import_js_imported[i] == script) {
                    found = true;
                    break;
                }

            if (found == false) {
                $("head").append('<script type="text/javascript" src="' + script + '"></script>');
                import_js_imported.push(script);
            }
        }
    });

})(jQuery);

Então tudo o que você precisa fazer para importar JavaScript é:

$.import_js('/path_to_project/scripts/somefunctions.js');

Eu também fiz um teste simples para isso no Example .

Ele inclui um arquivo main.js no HTML principal e, em seguida, o script em main.js usa $.import_js() para importar um arquivo adicional chamado included.js , que define esta função:

function hello()
{
    alert("Hello world!");
}

E logo depois de incluir o included.js , a função hello() é chamada e você recebe o alerta.

(Esta resposta é em resposta ao comentário do e-satis).


A import instruções está no ECMAScript 6.

Sintaxe

import name from "module-name";
import { member } from "module-name";
import { member as alias } from "module-name";
import { member1 , member2 } from "module-name";
import { member1 , member2 as alias2 , [...] } from "module-name";
import name , { member [ , [...] ] } from "module-name";
import "module-name" as name;

Você também pode montar seus scripts usando PHP :

Arquivo main.js.php :

<?php
    header('Content-type:text/javascript; charset=utf-8');
    include_once("foo.js.php");
    include_once("bar.js.php");
?>

// Main JavaScript code goes here

Melhor usar o modo jQuery . Para atrasar o evento pronto, primeiro ligue $.holdReady(true). Exemplo ( source ):

$.holdReady(true);
$.getScript("myplugin.js", function() {
    $.holdReady(false);
});

Se você quiser em JavaScript puro, você pode usar document.write .

document.write('<script src="myscript.js" type="text/javascript"></script>');

Se você usar a biblioteca jQuery, poderá usar o método $.getScript .

$.getScript("another_script.js");

Este script adicionará um arquivo JavaScript ao topo de qualquer outra <script>tag:

(function () {
    var li = document.createElement('script'); 
    li.type = 'text/javascript'; 
    li.src= "http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"; 
    li.async=true; 
    var s = document.getElementsByTagName('script')[0]; 
    s.parentNode.insertBefore(li, s);
})();

Se a sua intenção de carregar o arquivo JavaScript estiver usando as funções do arquivo importado / incluído , você também pode definir um objeto global e definir as funções como itens de objeto. Por exemplo:

global.js

A = {};

file1.js

A.func1 = function() {
  console.log("func1");
}

file2.js

A.func2 = function() {
  console.log("func2");
}

main.js

A.func1();
A.func2();

Você só precisa ter cuidado ao incluir scripts em um arquivo HTML. A ordem deve ser como abaixo:

<head>
  <script type="text/javascript" src="global.js"></script>
  <script type="text/javascript" src="file1.js"></script>
  <script type="text/javascript" src="file2.js"></script>
  <script type="text/javascript" src="main.js"></script>
</head>

A @importsintaxe para conseguir JavaScript importando CSS é possível usando uma ferramenta como o Mixture através de seu .mixtipo de arquivo especial (veja here ). Eu imagino que o aplicativo simplesmente usa um dos métodos mencionados anteriormente, embora eu não saiba.

Da documentação do Mixture em .mixarquivos:

Os arquivos de mixagem são simplesmente arquivos .js ou .css com .mix. no nome do arquivo. Um arquivo de mixagem simplesmente estende a funcionalidade de um estilo normal ou arquivo de script e permite que você importe e combine.

Aqui está um .mixarquivo de exemplo que combina vários .jsarquivos em um:

// scripts-global.mix.js
// Plugins - Global

@import "global-plugins/headroom.js";
@import "global-plugins/retina-1.1.0.js";
@import "global-plugins/isotope.js";
@import "global-plugins/jquery.fitvids.js";

A mistura produz isto como scripts-global.jse também como uma versão minificada ( scripts-global.min.js).

Nota: Eu não sou de forma alguma afiliado ao Mixture, além de usá-lo como uma ferramenta de desenvolvimento de front-end. Eu me deparei com essa questão ao ver um .mixarquivo JavaScript em ação (em um dos boilerplates da Mixture) e ficar um pouco confuso com ele ("você pode fazer isso?", Pensei comigo mesmo). Então percebi que era um tipo de arquivo específico do aplicativo (um pouco decepcionante, concordado). No entanto, imaginei que o conhecimento poderia ser útil para os outros.

ATUALIZAÇÃO : A mistura agora está livre (offline).

ATUALIZAÇÃO : A mistura agora está descontinuada. Lançamentos antigos da mistura ainda estão disponíveis


Há também Head.js . É muito fácil lidar com:

head.load("js/jquery.min.js",
          "js/jquery.someplugin.js",
          "js/jquery.someplugin.css", function() {
  alert("Everything is ok!");
});

Como você vê, é mais fácil do que o Require.js e tão conveniente quanto o $.getScriptmétodo do jQuery . Ele também possui alguns recursos avançados, como carregamento condicional, detecção de recursos e muito mais .


Talvez você possa usar essa função que encontrei nesta página Como incluo um arquivo JavaScript em um arquivo JavaScript? :

function include(filename)
{
    var head = document.getElementsByTagName('head')[0];

    var script = document.createElement('script');
    script.src = filename;
    script.type = 'text/javascript';

    head.appendChild(script)
}

var js = document.createElement("script");

js.type = "text/javascript";
js.src = jsFilePath;

document.body.appendChild(js);

Outra maneira, que na minha opinião é muito mais limpa, é fazer um pedido Ajax síncrono em vez de usar uma tag <script> . Qual é também como as manipulações do Node.js incluem.

Aqui está um exemplo usando jQuery:

function require(script) {
    $.ajax({
        url: script,
        dataType: "script",
        async: false,           // <-- This is the key
        success: function () {
            // all good...
        },
        error: function () {
            throw new Error("Could not load script " + script);
        }
    });
}

Você pode então usá-lo em seu código como usaria normalmente um include:

require("/scripts/subscript.js");

E ser capaz de chamar uma função do script necessário na próxima linha:

subscript.doSomethingCool(); 

Existem muitas respostas em potencial para essa questão. Minha resposta é obviamente baseada em vários deles. Foi com isso que acabei lendo todas as respostas.

O problema $.getScripte realmente qualquer outra solução que requeira um retorno de chamada quando o carregamento é concluído é que se você tiver vários arquivos que o utilizam e dependem um do outro, você não terá mais como saber quando todos os scripts foram carregados (uma vez que estejam aninhados) em vários arquivos).

Exemplo:

file3.js

var f3obj = "file3";

// Define other stuff

file2.js:

var f2obj = "file2";
$.getScript("file3.js", function(){

    alert(f3obj);

    // Use anything defined in file3.
});

file1.js:

$.getScript("file2.js", function(){
    alert(f3obj); //This will probably fail because file3 is only guaranteed to have loaded inside the callback in file2.
    alert(f2obj);

    // Use anything defined in the loaded script...
});

Você está certo quando diz que pode especificar o Ajax para ser executado de forma síncrona ou usar XMLHttpRequest , mas a tendência atual parece ser descontinuar solicitações síncronas, portanto, talvez você não obtenha suporte completo ao navegador agora ou no futuro.

Você poderia tentar usar $.whenpara verificar uma matriz de objetos adiados, mas agora você está fazendo isso em cada arquivo e o arquivo2 será considerado carregado assim que a $.whenexecução não for executada quando o retorno de chamada for executado, portanto o arquivo1 continuará a execução antes que o arquivo3 seja carregado . Isso realmente ainda tem o mesmo problema.

Eu decidi ir para trás em vez de para frente. Obrigado document.writeln. Eu sei que é um tabu, mas desde que seja usado corretamente, isso funciona bem. Você acaba com o código que pode ser depurado facilmente, mostra o DOM corretamente e pode garantir a ordem em que as dependências sejam carregadas corretamente.

É claro que você pode usar $ ("body"). Append (), mas você não pode mais depurar mais corretamente.

NOTA: Você deve usar isso somente enquanto a página estiver carregando, caso contrário, você obterá uma tela em branco. Em outras palavras, sempre coloque isso antes / fora do document.ready . Eu não testei usando isso depois que a página é carregada em um evento de clique ou algo assim, mas tenho certeza que irá falhar.

Gostei da idéia de estender o jQuery, mas obviamente você não precisa.

Antes de chamar document.writeln, ele verifica se o script ainda não foi carregado, avaliando todos os elementos do script.

Eu suponho que um script não seja totalmente executado até que seu document.readyevento tenha sido executado. (Eu sei que usar document.readynão é necessário, mas muitas pessoas o usam, e lidar com isso é uma proteção.)

Quando os arquivos adicionais são carregados, os document.readyretornos de chamada serão executados na ordem errada. Para resolver isso quando um script é realmente carregado, o script que o importou é reimportado e a execução é interrompida. Isso faz com que o arquivo de origem agora tenha seu document.readyretorno de chamada executado após qualquer um dos scripts importados.

Em vez dessa abordagem, você poderia tentar modificar o jQuery readyList, mas isso parecia uma solução pior.

Solução:

$.extend(true,
{
    import_js : function(scriptpath, reAddLast)
    {
        if (typeof reAddLast === "undefined" || reAddLast === null)
        {
            reAddLast = true; // Default this value to true. It is not used by the end user, only to facilitate recursion correctly.
        }

        var found = false;
        if (reAddLast == true) // If we are re-adding the originating script we do not care if it has already been added.
        {
            found = $('script').filter(function () {
                return ($(this).attr('src') == scriptpath);
            }).length != 0; // jQuery to check if the script already exists. (replace it with straight JavaScript if you don't like jQuery.
        }

        if (found == false) {

            var callingScriptPath = $('script').last().attr("src"); // Get the script that is currently loading. Again this creates a limitation where this should not be used in a button, and only before document.ready.

            document.writeln("<script type='text/javascript' src='" + scriptpath + "'></script>"); // Add the script to the document using writeln

            if (reAddLast)
            {
                $.import_js(callingScriptPath, false); // Call itself with the originating script to fix the order.
                throw 'Readding script to correct order: ' + scriptpath + ' < ' + callingScriptPath; // This halts execution of the originating script since it is getting reloaded. If you put a try / catch around the call to $.import_js you results will vary.
            }
            return true;
        }
        return false;
    }
});

Uso:

Arquivo3:

var f3obj = "file3";

// Define other stuff
$(function(){
    f3obj = "file3docready";
});

Arquivo2:

$.import_js('js/file3.js');
var f2obj = "file2";
$(function(){
    f2obj = "file2docready";
});

Arquivo1:

$.import_js('js/file2.js');

// Use objects from file2 or file3
alert(f3obj); // "file3"
alert(f2obj); // "file2"

$(function(){
    // Use objects from file2 or file3 some more.
    alert(f3obj); //"file3docready"
    alert(f2obj); //"file2docready"
});

O problema com o seu código é que o JavaScript faz distinção entre maiúsculas e minúsculas. Sua chamada de método

indexof()

deve ser realmente

indexOf()

Tente corrigi-lo e veja se isso ajuda:

if (test.indexOf("title") !=-1) {
    alert(elm);
    foundLinks++;
}






javascript file import include