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

时间:2012-12-07 11:32:45

标签: javascript jquery 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直到循环结束。

7 个答案:

答案 0 :(得分:1)

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
  }
}())

答案 1 :(得分:1)

查看其他人的答案我只能这样做。 更改您的实施:

 $.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 );    
  }
});

答案 2 :(得分:1)

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

回答你的问题:

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

答案 3 :(得分:1)

你得到这个是因为$ .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

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

使用承诺

如果您使用的是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完成时然后getWidgetContent调用widget函数。 then方法返回一个在任何内部方法promise完成时完成的promise。

我知道它开始听起来很复杂,但是要玩游戏并尝试它。 :)

答案 4 :(得分:0)

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

window.global_widget_id = "foo";

然后您可以这样引用它:

var myId = window.global_widget_id;

并覆盖它:

window.global_widget_id = "newId";

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

修改

似乎$.getScript()个文件不属于全局范围:jQuery's getScript - including files into the main scope?

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

答案 5 :(得分:0)

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

在我看来,这样做:

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面对它,我试着像上面那样做变量 如果成功,请打电话给我,祝你好运

答案 6 :(得分:0)

如果您不想按顺序执行代码,那么您将不得不重写一下。在前一个调用其回调之前,不应该对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);