2

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

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直到循环完成。

4

7 回答 7

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
  }
}())
于 2012-12-07T12:44:07.977 回答
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 );    
  }
});
于 2012-12-15T01:15:15.267 回答
1

getWidgetContent 正在执行getScript,但getScript立即返回,而不是等待网络(与 CPU 相比相对较慢)完成获取脚本。这不是一个错误,而是一件了不起的事情——通过异步编程,您可以在 CPU 上完成大量工作,如果您不想等待比 CPU 慢得多的事情,您不必等待!

要回答您的问题:

  • 要在脚本请求完成时设置全局变量,只需将变量赋值移动到您的回调函数中。
  • 简单地让所有人getScripts同时运行会更快,但如果你真的不能让第二个getScript开始直到第一个完成,getWidgetContent只调用一次,让你的回调确定下一个小部件并getWidgetContent再次调用它。
于 2012-12-17T03:06:27.987 回答
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 及更高版本,则可以通过链接Promise来确保getWidgetContent按顺序调用。但是,这种方法的缺陷是您不会同时加载所有脚本请求,请求将在前一个完成后一个接一个地发送。

确保返回 $.getScript 的结果,它是一个延迟对象(我在这里做了最小的更改,只需注意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方法返回一个当任何内部方法承诺完成时完成的承诺。

我知道它开始听起来很复杂,但是请尝试一下并尝试一下。:)

于 2012-12-17T10:22:39.510 回答
0

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

window.global_widget_id = "foo";

然后,您可以像这样引用它:

var myId = window.global_widget_id;

并覆盖它:

window.global_widget_id = "newId";

$变量赋值中的 jQuery 也可能会混淆。)(不正确。忽略最后一部分。)

编辑:

看起来$.getScript()文件不是全局范围的一部分:jQuery的getScript - 将文件包括在主范围中?.

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

于 2012-12-07T11:39:12.123 回答
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,我试着像上面那样做变量如果成功给我打电话,祝你好运

于 2012-12-17T10:32:10.723 回答
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);
于 2012-12-17T10:40:14.757 回答