【问题标题】:Wait for Javascript function finished inside foreach cshtml?等待 foreach cshtml 中的 Javascript 函数完成?
【发布时间】:2014-12-02 10:24:38
【问题描述】:

我正在尝试使用 Javascript 进行简单的自动输入。我的问题是,如果我从视图 (.cshtml) 中调用它,自动输入将无法按顺序运行。

我的cshtml是这样的:

<script type="text/javascript" src="@Url.Content("/Scripts/autotype.js")"></script>

@foreach (var temp in @Model)
{
    <script>
        auto_type("ABCDEFG", 0)
    </script>
}

<div id="divauto"></div>

它是 autotype.js :

function auto_type(wrt, i) {

    wrt = wrt.split('');
    var delay = 100;
    while (i < wrt.length) {
        setTimeout(function () {
            $('#divauto').append(wrt.shift())
        }, delay * i)
        i++;
    }
}

从这些代码中,输出将类似于“AAABBBCCCDDDEEEFFFGGG”,但我需要的输出类似于:“ABCDEFGABCDEFGABCDEFG”

【问题讨论】:

  • 输出是“ABCDEFG”,而不是“AAABBBCCC...”。
  • 我在我的 repro 中得到了这个 AAAAABBBBBCCCCCDDDDDEEEEE
  • 我真的会质疑您是否需要使用 Razor 在这样的循环中输出脚本。为客户端行为保留脚本几乎总是更好,而将 Razor 用于服务器端行为。您当然可以使用 Razor 为您的客户端代码提供数据以进行操作,但是尝试像这样将两者混合使用是自找麻烦。

标签: javascript asp.net-mvc asp.net-mvc-4 razor


【解决方案1】:

您可以使用jQuery deferreds 执行此操作。在这种情况下,我必须使用两个递归函数,因为您需要对通过 viewItems 列表的迭代以及启动setInterval() 以更新每个字符的#divAuto 进行流控制。

作为此处如何使用承诺来添加控制的示例,在autoType() 中,您会从新的autoTypeUtil() 返回一个承诺。当 Promise 在 autoTypeUtil() 内解决时,您再次使用剩余列表调用 autoType()。这使您可以在异步运行的同时对输入项进行流控制。

您可以查看fiddle 以获取工作示例。

function timeString(arr, timeFactor, deferred) {
    if (arr.length === 0) { deferred.resolve(); }

    var ch = arr.shift();
    var deferredInternal = new $.Deferred();
    var promise = deferredInternal.promise();
    var delay = 100;

    setTimeout(function () {
        $('#divauto').append(ch);
        deferredInternal.resolve("done");
    }, delay * timeFactor)

    promise.done(function() { 
        timeString(arr, timeFactor, deferred); 
    });
}

function autoTypeUtil(inputString, timeFactor) {
    var deferredTimeString = new $.Deferred();
    var deferredInternal = new $.Deferred();
    var promiseTimeString = deferredTimeString.promise();

    inputString = inputString.split('');
    timeString(inputString, timeFactor, deferredTimeString);

    promiseTimeString.then(function() {
        deferredInternal.resolve()
    });
    return deferredInternal.promise();
}

function autoType(arr, timeFactor) {
    if (arr.length === 0) { return; }

    var promise = autoTypeUtil(arr.shift(), timeFactor);

    promise.done(function() {
        autoType(arr, timeFactor);
    });
}

var viewItems = ["I", "love", "jQuery", "promises"];
autoType(viewItems, 1);

【讨论】:

    【解决方案2】:

    我认为您正在寻找的是打字机或电传打字机效果,其中文本像打字机一样写出来?

    在这种情况下,请查看这个 SO question,因为它看起来会提供您需要的东西。

    Typewriter Effect with jQuery

    【讨论】:

      【解决方案3】:

      问题是 i 在循环结束时被设置为 7,这发生在它被调用的第一个实例之前。试试这样的:

      function auto_type(wrt) {
          wrt = wrt.split('');
          if (wrt.length > 0) {
              var delay = 100;
              type_loop(wrt, delay);    
          }
      }
      
      function type_loop(wrt, delay) {
          var myTimeout = setTimeout(function () {
              clearTimeout(myTimeout);
              $('#divauto').text($('#divauto').text() + wrt.shift());
              if (wrt.length > 0) {
                  type_loop(wrt, delay);
              }
          }, delay);
      }
      
      $(document).ready(function() {
          auto_type("ABCDEFG", 0);
      });
      

      这个方法称为tail recursion,以防你好奇。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-16
        • 2020-06-10
        相关资源
        最近更新 更多