难以使用全局变量和$ .getScript

我有以下脚本无法正常工作:

function getWidgetContent( widget ) { if(widget.script!=null){ $global_widget_id = widget.widget_id; $.getScript( "js/" + widget.script, function() { $( ".widget_header_title_" + widget.widget_id ).append( widget.title ); }); } } 

这称为如下:

 for ( j = 0; j <= widget_data.d.length - 1; j++ ) { getWidgetContent( widget_data.d[j] ); } 

我认为这将在函数内运行函数,为全局值赋值,然后在循环的每次迭代中运行$.getScript 。 但那并没有发生。 它似乎循环遍历循环,直到循环结束,让我们说它循环3次,每次为全局值赋值,即3次,然后它最终去并执行$.getScript

因为它现在只能使用$ .getScript文件中的全局值的最后一次分配3次…

如何更改此值以便为全局变量赋值,运行$.getScript 。 完成后,继续使用原始循环,将下一个值分配给全局变量,运行$.getScript直到循环结束。

你得到这个是因为$ .getScript是一个异步方法。 在这种情况下,这意味着该方法在脚本完成加载之前立即返回,并继续在其后执行代码。

这意味着什么:

 $.getScript('a.js', function () { console.log('Loaded a'); }); $.getScript('b.js', function () { console.log('Loaded b'); }); $.getScript('c.js', function () { console.log('Loaded c'); }); // Output could be: // Loaded c // Loaded a // Loaded b 

这意味着所有脚本文件请求可以同时完成,但这也意味着订单不是确定性的(固定的)。

使用Promises

如果使用jQuery 1.5及更高版本,可以通过链接promises来确保顺序调用getWidgetContent 。 但是,这种方法的缺陷在于您不会同时加载所有脚本请求,请求将在前一个请求完成后一个接一个地发送。

确保返回$ .getScript的结果,这是一个Deferred Object (我在这里做了很少的更改,只需注意return语句):

 function getWidgetContent( widget ) { if(widget.script!=null){ $global_widget_id = widget.widget_id; return $.getScript( "js/" + widget.script, function() { $( ".widget_header_title_" + widget.widget_id ).append( widget.title ); }); } return null; } 

在完成先前的承诺之后执行新的getWidgetContent的新方法(完成上一个操作):

 function doGetWidgetContentAfter(promise, widget) { return promise.then(function () { return getWidgetContent( widget ); }); } 

打电话给:

 var promise = $.when(true); for ( j = 0; j <= widget_data.d.length - 1; j++ ) { promise = doGetWidgetContentAfter( promise, widget_data.d[j] ); } 

说明

doGetWidgetContentAfter做的是当所述promise完成时, 然后调用widgetgetWidgetContent函数。 then方法返回一个promise,它在任何内部方法promise完成时完成。

我知道它开始听起来很复杂,但确实可以玩并试验它。 🙂

看其他人的答案,我只能这么想。 更改您的实施:

  $.getScript( "js/" + widget.script, function() { $( ".widget_header_title_" + widget.widget_id ).append( widget.title ); }); 

到相应的ajax调用,但不是异步

 $.ajax({ url: "js/" + widget.script, dataType: "script", async: false, success: function() { $( ".widget_header_title_" + widget.widget_id ).append( widget.title ); } }); 

getWidgetContent 正在执行getScript ,但是getScript立即返回而不是等待网络(与CPU相比相对较慢)来完成脚本的获取。 这不是一个bug,而是一个很棒的东西 – 使用异步编程,你可以在CPU上完成大量的工作,如果你不想要,你不必等待比CPU慢很多的东西。 !

回答你的问题:

  • 要在脚本请求完成时设置全局变量,只需将变量赋值移动到回调函数中。
  • 简单地允许所有getScripts一次运行会更快,但是如果你真的不能允许第二个getScript在第一次完成之前启动,只需调用一次getWidgetContent ,然后让你的回调确定下一个widget, getWidgetContent再调用getWidgetContent它。

getScript方法是异步的,因此在从包含脚本值的服务器获得响应之前,循环将运行下一次迭代
这就是为什么我们必须发送一个回调函数。 一旦服务器响应,javascript就知道该怎么做。 所以虽然普通循环无法帮助我们,但我们可以使用重复函数。 我们得到的回调函数是调用loopFunc然后移动到集合/数组中的下一个项目。 我跳了这个可以给你带来灵感:

 var getWidgetContent = function(wiget, loopFunc) { if(widget.script!=null){ $global_widget_id = widget.widget_id $.getScript( "js/" + widget.script, function() { $( ".widget_header_title_" + widget.widget_id ).append( widget.title ) loopFunc() //now we got a response from the server and want to move on to the next script tag. }) } } var i = 0 (function loopFunc(){ //we define a function and call it instantly if(i < widget_data.d.length){ getWidgetContent(widget_data.d,loopFunc) //now we call the getWidgetContent but we send in the current function aswell console.log($global_widget_id) // this is going to change each time i += 1 } }()) 

尝试将变量分配给窗口命名空间:

 window.global_widget_id = "foo"; 

然后你可以像这样引用它:

 var myId = window.global_widget_id; 

并覆盖它:

 window.global_widget_id = "newId"; 

(变量赋值中的$也可能让jQuery感到困惑。) (不正确。忽略最后一部分。)

编辑:

看来$.getScript()文件不属于全局范围: jQuery的getScript – 包括进入主范围的文件? 。

也许你可以从回调而不是嵌入的document.ready()调用$.getScript()函数,并通过这种方式传递变量?

可能它可以帮助你,在循环中放置函数可以重写其中包含的变量

在我看来,这样做:

 function getWidgetContent(widget) { if(w_script != null){ // And make variable for make sure each values come // from parent function and not from `$.getScript` var w_script = widget.script; var w_widget_id = widget.widget_id; var w_title = widget.title; $.getScript( "js/" + w_script, function() { $( ".widget_header_title_" + w_widget_id ).append( w_title ); }); } } 

这个案子面对我,但是我在$.ajax上面对它,我试着像上面那样变量如果成功请给我打电话,祝你好运

如果您不想按顺序执行代码,那么您将不得不重写一下。 下一次调用getScript不应该在前一个调用它的回调之前完成。 这可以通过从回调中调用getWidgetContent来完成…

就像是:

 function getWidgetContent(d, index) { var widget = d[index]; if(widget.script!=null){ $global_widget_id = widget.widget_id; $.getScript( "js/" + widget.script, function() { $( ".widget_header_title_" + widget.widget_id ).append( widget.title ); if (index <= d.length - 1) getWidgetContent(d,index+1); //call the next one }); } } //Start the calls getWidgetContent( widget_data.d,0);