0

我正在使用发布在以下位置的插件代码:

jQuery 提示和技巧

...这本质上是一个异步计时器循环:

jQuery.forEach = function (in_array, in_pause_ms, in_callback)
{
    if (!in_array.length) return; // make sure array was sent

    var i = 0; // starting index

    bgEach(); // call the function

    function bgEach()
    {
        if (in_callback.call(in_array[i], i, in_array[i]) !== false)
        {
            i++; // move to next item

            if (i < in_array.length) setTimeout(bgEach, in_pause_ms);
        }
    }

    return in_array; // returns array
};


jQuery.fn.forEach = function (in_callback, in_optional_pause_ms)
{
    if (!in_optional_pause_ms) in_optional_pause_ms = 10; // default

    return jQuery.forEach(this, in_optional_pause_ms, in_callback); // run it
};

在这个伟大社区的帮助下,我了解到如果我“回归真实”;或“返回错误;” 它与继续循环的下一次迭代具有相同的效果。

我想做的是以编程方式完全杀死(销毁) $.forEach 循环调用,不允许剩余的迭代运行。

我如何向该插件添加一个方法,以允许我终止对该插件的特定调用,同时不影响同时运行的其他调用?

我考虑过将调用分配给这样的变量:

var foo = $.forEach(json, 1000, function(idx,item) { /* do stuff */ });

...稍后引用特定实例而不影响其他实例,但是如何添加 kill 方法并在 foo 上调用它?我需要与 ajax 调用一起使用的 foo.abort() 等效项。

可以做到吗?如果是这样,怎么做?

4

2 回答 2

0

这实际上只是示例代码,所以它有一些问题。

您可以通过简单地将 expando 属性添加到 in_array 对象来缓解这种情况:

jQuery.forEach = function (in_array, in_pause_ms, in_callback)
{
    // Note, you should use $.isArray(), which is smarter than checking length.
    if (!$.isArray(in_array)) return false;
    in_array.valid = true;
    var i = 0; // starting index
    function bgEach()
    {
        if (!in_array.valid) return;
        if (in_callback.call(in_array[i], i, in_array[i]) !== false)
        {
            i++; // move to next item

            if (i < in_array.length) setTimeout(bgEach, in_pause_ms);
        }
    }

    // I moved this because you were calling it before it was defined.
    bgEach(); // call the function
    return in_array; // returns array
};

由于您从方法中获取原始数组对象,因此您可以在完成后将对象的“有效”属性设置为 false:

var foo = $.forEach(json, 1000, function(idx,item) { /* do stuff */ });
foo.valid = false;

由于该valid属性取消了 setTimeout 递归,这将有效地终止循环。

请注意,这种代码有些危险。你会遇到竞争条件等等,但是当你开始在 JS 中执行伪线程和异步代码时就会发生这种情况。

于 2012-04-13T01:39:42.527 回答
-1

您可以将计时器传递给回调并更改

if (i < in_array.length) setTimeout(bgEach, in_pause_ms);

if (i == in_array.length) clearTimeout(timeout);

这将保证它只会循环与项目一样多的次数。

这是 jQuery forEach:

jQuery.forEach = function (in_array, in_pause_ms, in_callback)
{
    if (!in_array.length) return; // make sure array was sent

    var i = 0; // starting index

    bgEach(); // call the function

    function bgEach(){
        var timeout;
        if (in_callback.call(in_array[i], i, in_array[i], timeout = setTimeout(bgEach, in_pause_ms)) !== false)
        {
            i++; // move to next item
            // if end of array, stop iterating
            if (i == in_array.length) clearTimeout(timeout);
        }
    }

    return in_array; // returns array
};

如果计时器满足某些条件,您可以使用它来清除计时器,从而结束循环。例子:

$.forEach([1,2,3], 1000, function(idx, item, timer) {
  if(item == 2) {
    clearTimeout(timer);
  }
});
于 2012-04-13T05:37:50.773 回答