我需要在加载某个脚本后执行一个函数,所以我使用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
的通话,但没有帮助。
答案 0 :(得分:1)
两件事:
函数SetInlineManualCallbacks
没有return
语句。因此,尽管问题2,SetInlineManualCallbacks(inlineUid)
应该返回undefined
。但是,success
需要功能:
success: SetInlineManualCallbacks.bind(null, inlineUid)
没有bind
的老派:
success: function() {
SetInlineManualCallbacks(inlineUid)
}
但是,SetInlineManualCallbacks
看起来不需要任何参数,所以在你的情况下这就足够了:
success: SetInlineManualCallbacks
它说window.inline_manual_player
是undefined
。从变量名称来看,我认为这是因为您刚刚加载了JS文件内容,如纯文本,但您没有将内容作为JavaScript执行。
您可以使用eval
在success
回调中执行它,但这确实是一个坏主意。我可能会在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]);
答案 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,而是有两个可能更好的可能性。
如果您愿意并且能够更新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);
}
});
如果编辑inline-manual-player.js不是一个选项,那么该文件的初始作者可能已经包含类似于window.inline-manual-player-callback-queue的内容。检查文件的文档,看看是否有一个全局方法或数组可以添加你的回调函数,让内联手动播放器自动调用它,一旦所有的异步魔法发生了
祝你好运!