如何在现有的jQuery插件中添加kill方法?

时间:2012-04-13 01:25:59

标签: javascript jquery jquery-plugins loops settimeout

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

jQuery Tips and Tricks

...这是一个异步定时器循环:

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

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

2 个答案:

答案 0 :(得分: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
};

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

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

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

请注意,这种代码有点危险。你会遇到竞争条件和诸如此类的东西,但是当你开始做伪线程时会发生这种情况。 JS中的异步代码。

答案 1 :(得分:-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);
  }
});
相关问题