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

时间:2016-07-28 16:20:28

标签: javascript jquery ajax

我需要在加载某个脚本后执行一个函数,所以我使用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.');
                }
            });
        }

我得到Uncaught TypeError: Cannot read property 'setCallbacks' of undefined

我尝试更改使用async:false的通话,但没有帮助。

9 个答案:

答案 0 :(得分:1)

两件事:

  1. 函数SetInlineManualCallbacks没有return语句。因此,尽管问题2,SetInlineManualCallbacks(inlineUid)应该返回undefined。但是,success需要功能

    success: SetInlineManualCallbacks.bind(null, inlineUid)
    

    没有bind的老派:

    success: function() {
        SetInlineManualCallbacks(inlineUid)
    }
    

    但是,SetInlineManualCallbacks看起来不需要任何参数,所以在你的情况下这就足够了:

    success: SetInlineManualCallbacks
    
  2. 它说window.inline_manual_playerundefined。从变量名称来看,我认为这是因为您刚刚加载了JS文件内容,如纯文本,但您没有将内容作为JavaScript执行。

    您可以使用evalsuccess回调中执行它,但这确实是一个坏主意。我可能会在DOM中插入<script>标记,而不是使用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)
    }
    

答案 1 :(得分:1)

为什么要用ajax加载?让浏览器做到这一点。

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

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

答案 2 :(得分:0)

当你这样做时

<meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value="originalPackageName.ui.MainActivity" />

您正在执行该方法并设置它返回成功回调的任何内容。当触发成功时,你并不是说这个。

应该只是

success: SetInlineManualCallbacks(inlineUid)

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

答案 3 :(得分:0)

正如有人建议的那样,Inline Manual正在该脚本中初始化。您的站点处于测试模式,因此脚本本身还有一个额外的ajax请求,用于检查用户是否可以访问它。因此脚本可能会加载,但inline_manual_player对象在加载时仍然不可用,因为在创建对象之前还有其他事情发生。

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

var inline_manual_player = inline_manual_player || []; inline_manual_player.push(['setCallbacks', my_callbacks]);

http://help.inlinemanual.com/docs/queuing-actions

答案 4 :(得分:0)

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

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

   //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:"use strict"; + jQuery.getScript() = script can't export to global namespace如前面提到的 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.');
        }
    });
}

这很有效!它不是最漂亮的,但它确实有效。
inline-manual工具的开发人员在这里作出回应( Marek )并提及我的网站处于“测试”模式下的事实。我们无法知道这会影响到什么。

答案 5 :(得分:0)

根据你的问题,你想要在正确加载另一个脚本后执行skript。

在您自己的回答中使用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.');
        }
    });
});

答案 6 :(得分:0)

当时似乎没有执行脚本。请注意,根据JQuery documentation加载脚本但未必执行后会触发回调。

如果要确保脚本已执行,可以在使用之前在HTML上同步加载脚本。如果你这样做,你将不需要ajax,你将保持你的代码简单。 KISS principle

如果您需要按照此处的方式进行操作,则可以应用观察者模式创建custom event

这是一个例子。

在文件“inline-manual-player.js”的末尾。你可以这样做。

$.event.trigger({
type: "fileExecuted");

然后,您将订阅“fileExecuted”事件,而不是成功回调。

$(document).on("fileExecuted", SetInlineManualCallbacks);

希望它有所帮助。

答案 7 :(得分:-1)

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的来源,那将会有所帮助。

答案 8 :(得分:-1)

似乎inline-manual-player.js异步加载window.inline_manual_player。这意味着在该文件的onload事件触发后允许线程在上移动但在加载window.inline_manual_player之前 。因此,您发现window.inline_manual_player在一段时间内未定义。这可能是由于inline-manual-player.js自己进行了ajax调用(或者是setTimeouts等等 - JavaScript是一个异步的野兽)。

不是设置一个丑陋的(没有冒犯)setTimeout,而是有两个可能更好的可能性。

1

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

window.inline-manual-player-callback-queue = [];

...以及稍后在该文件中,在异步定义window.inline_manual_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]();
}

最后,在您的初始文件中输入以下内容:

function addCallback() {
    window.inline_manual_player.setCallbacks({
        onTopicDone: function (player, topic_id, step_id) {
            console.log('Step was displayed.');
        }
    });
}

$.ajax({
    url: "../Scripts/inline-manual-player.js",
    dataType: "script",
    beforeSend: function () {
        loader.hide();
        loader.unbind();
    },
    success: function() {
        // Because you've defined window.inline-manual-player-callback-queue at the start of inline-manual-player.js, the following will be available upon onload (aka success) of that file:
        window.inline-manual-player-callback-queue.push(addCallback);
    }
});

2

如果编辑inline-manual-player.js不是一个选项,那么该文件的初始作者可能已经包含类似于window.inline-manual-player-callback-queue的内容。检查文件的文档,看看是否有一个全局方法或数组可以添加你的回调函数,让内联手动播放器自动调用它,一旦所有的异步魔法发生了

祝你好运!