Javascript 无法使用jquery Ajax请求加载脚本

Javascript 无法使用jquery Ajax请求加载脚本,javascript,jquery,ajax,Javascript,Jquery,Ajax,我需要在加载某个脚本后执行一个函数,因此我使用ajax调用加载脚本,成功后,我调用了一个函数,该函数使用了一个假定已从该脚本加载的对象,我得到一个错误,即该对象未定义。 这是我的密码: function LoadInlineManualScript() { return $.ajax({ url: "../Scripts/inline-manual-player.js", dataType: "script", befo

我需要在加载某个脚本后执行一个函数,因此我使用ajax调用加载脚本,成功后,我调用了一个函数,该函数使用了一个假定已从该脚本加载的对象,我得到一个错误,即该对象未定义。 这是我的密码:

function LoadInlineManualScript() {
  return $.ajax({
            url: "../Scripts/inline-manual-player.js",
            dataType: "script",
            beforeSend: function () {
                loader.hide();
                loader.unbind();
            },
            success: SetInlineManualCallbacks
        });
    }


function SetInlineManualCallbacks() {
            debugger;
            //Here I get the error!
            window.inline_manual_player.setCallbacks({
                onTopicDone: function (player, topic_id, step_id) {
                    console.log('Step was displayed.');
                }
            });
        }
我得到了
uncaughttypeerror:无法读取未定义的
的属性“setCallbacks”

我尝试将调用更改为使用
async:false
,但没有帮助。

当您执行此操作时

success: SetInlineManualCallbacks(inlineUid)
您正在执行该方法,并将其返回的内容设置为success回调。你不是说在触发成功时调用它

应该是

success: SetInlineManualCallbacks

但是我认为Ajax调用本身存在一个问题,您正在加载一个脚本并期望它做一些事情,我不认为Ajax调用是您想要的。如果脚本只是返回
inlineUid
为什么要使用脚本而不是JSON或文本调用。如果
inlineUid
是全局的,则只需在回调方法中读取它。如果不知道脚本文件中发生了什么,就很难给出完整的答案。

success
接受函数而不是值。除非
SetInlineManualCallbacks
返回另一个函数,否则使用
bind
并部分应用参数

function LoadInlineManualScript() {
  return $.ajax({
            url: "../Scripts/inline-manual-player.js",
            dataType: "script",
            beforeSend: function () {
                loader.hide();
                loader.unbind();
            },
            success: SetInlineManualCallbacks.bind(null, inlineUid)
        });
    }
如果您能解释一下inlineUid的来源,这会有所帮助。

有两件事:

  • 函数
    SetInlineManualCallbacks
    没有
    return
    语句。因此,尽管存在问题2,
    SetInlineManualCallbacks(inlineUid)
    应该返回
    undefined
    。但是,
    成功
    需要一个功能

    success: SetInlineManualCallbacks.bind(null, inlineUid)
    
    或者没有绑定的旧式学校:

    success: function() {
        SetInlineManualCallbacks(inlineUid)
    }
    
    但是,看起来
    SetInlineManualCallbacks
    不需要任何参数,因此在您的情况下这就足够了:

    success: SetInlineManualCallbacks
    
  • 它显示的是
    窗口。内联\u手动\u播放器
    未定义的
    。从变量名判断,我认为这是因为您刚刚加载了JS文件内容,作为纯文本,但没有作为JavaScript执行内容

    您可以使用
    eval
    success
    回调中执行它,但这确实是个坏主意。我可能会在DOM中插入一个
    标记,而不是使用AJAX

    function LoadInlineManualScript() {
        var s = document.createElement('script')
        s.src = "../Scripts/inline-manual-player.js"
        // your callback will fire when the script is loaded and executed
        s.onload = SetInlineManualCallbacks
        // it will start to load right after appended, and execute of course
        document.body.appendChild(s)
    }
    

  • 正如有人建议的,内联手册正在该脚本中初始化自身。您的站点处于测试模式,因此脚本本身中还有一个额外的ajax请求,用于检查用户是否可以访问它。因此,脚本可能会加载,但是内联的手动播放器对象在加载时还不可用,因为在它创建对象之前还有其他事情发生

    如果要在对象可用之前设置回调,可以在调用脚本加载之前使用队列操作

    var inline_manual_player=inline_manual_player | |[];
    内联手动播放器推送(['setCallbacks',my_callbacks])


    这个答案是我在这里得到的一些答案的组合:

    我用来加载脚本而不是使用Jquery的
    $的函数是:

       //Must load the script after inlineManualTracking object is ready.
        function LoadInlineManualScript() {
            loader.hide();
            loader.unbind();
            var script = document.createElement('script');
            script.src = "../Scripts/inline-manual-player.js";
            // your callback will fire when the script is loaded and executed
            script.onload = WaitForInlineManualScriptToLoad;
            // it will start to load right after appended, and execute of course
            document.body.appendChild(script);
        }
    
    我加载的脚本有
    use strict
    ,无法用jquery加载,原因如下:如前面提到的epascarello

    即使在使用了Leo的回答之后,我仍然对该对象有问题,这就是为什么我在脚本的onload事件之后使用以下函数的原因

    function WaitForInlineManualScriptToLoad() {
        if (typeof window.inline_manual_player == 'undefined') {
            setTimeout(WaitForInlineManualScriptToLoad, 100);
            return;
        }
        InitInlineManualPlayerCallBacks();
    }
    
    function InitInlineManualPlayerCallBacks() {
        window.inline_manual_player.setCallbacks({
            onTopicDone: function (player, topic_id, step_id) {
                console.log('Step was displayed.');
            }
        });
    }
    

    这很有效这不是最漂亮的,但它很管用。
    内联手册
    工具的开发者在这里(Marek)做出了回应,并提到我的网站处于“测试”模式下。我们不可能知道这会影响。

    看起来inline-manual-player.js异步加载
    window.inline\u manual\u player
    。这意味着线程可以在该文件的onload事件触发后,但在
    窗口。inline_manual_player
    加载之前继续移动。因此,您会发现
    window.inline\u manual\u player
    在一段时间内没有定义。这可能是由于inline-manual-player.js自己进行ajax调用(或设置超时等)——JavaScript是一种异步beast

    与其设置一个丑陋的(没有冒犯)设置超时,还有两种可能更好

    1. 如果您愿意并且能够更新inline-manual-player.js,您可以在该文件的顶部添加类似的内容:

    window.inline-manual-player-callback-queue = [];
    
    。。。稍后在该文件中,在异步定义了
    窗口.inline\u manual\u player
    之后,添加:

    // I've made this an array, in case you'd like to add multiple functions to be called upon window.inline-manual-player being ready.
    var queue = window.inline-manual-player-callback-queue;
    var length = queue.length;
    var i = 0;
    for(i; i<length; i++) {
        queue[i]();
    }
    
    2. 如果不选择编辑inline-manual-player.js,则该文件的初始作者可能已经包含类似于window.inline-manual-player-callback-queue的内容。检查该文件的文档,看看是否有一个全局方法或数组可以添加回调函数,让inline-manual-player.js在所有异步魔法发生后自动调用它


    祝你好运

    根据您的问题,您希望在正确加载另一个脚本后执行SKcript

    在您自己的答案中,使用jQuery“getScript”函数对您来说是行不通的,那么,为什么不尝试一下不使用jQuery的老式方法呢

    创建一个新的脚本元素,将其添加到文档头,并在readystate上设置回调函数

    function loadScript(url, callback) {
        var newScript = document.createElement( "script" )
        newScript.type = "text/javascript";
        if(newScript.readyState) {  //IE
            newScript.onreadystatechange = function() {
                if (newScript.readyState === "loaded" || newScript.readyState === "complete") {
                    newScript.onreadystatechange = null;
                    callback();
                }
            };
        } else {  //Others
            newScript.onload = function() {
                callback();
            };
        }
        newScript.src = url;
        document.getElementsByTagName("head")[0].appendChild( newScript );
    }
    
    现在,您可以调用已定义的方法并提供回调函数,在您的情况下,这将是:

    loadScript("../Scripts/inline-manual-player.js", function() {
        debugger;
        // should work now
        window.inline_manual_player.setCallbacks({
            onTopicDone: function (player, topic_id, step_id) {
                console.log('Step was displayed.');
            }
        });
    });
    

    为什么要用ajax加载?让浏览器来做吧

    函数loadScript在DOM上插入脚本,并将回调附加到脚本元素的事件
    onload

    function loadScript(href_script, callback) {
        var script = document.createElement('script');
        script.src = href_script;
        script.onload = callback;
    
        // The same code used by Google Analytics
        var x = document.getElementsByTagName('script')[0];
        x.parentNode.insertBefore(script, x);
    };
    
    function SetInlineManualCallbacks() {
      debugger;
      //Here I get the error!
      console.log("Code Running");
    }
    
    这里有一个例子:

    loadScript("//www.google-analytics.com/analytics.js", SetInlineManualCallbacks);
    

    当时似乎没有执行脚本。请注意,一旦加载脚本,就会触发回调,但不一定是exec
    loadScript("//www.google-analytics.com/analytics.js", SetInlineManualCallbacks);
    
    $.event.trigger({
    type: "fileExecuted");
    
    $(document).on("fileExecuted", SetInlineManualCallbacks);