繁体   English   中英

按顺序多次运行 jQuery 函数(对于 Bookmarklet)

[英]Running a jQuery function multiple times sequentially (for a Bookmarklet)

我在 Bookmarklet 中使用了以下 jQuery 代码。 它逐个点击页面上的所有按钮(带有“取消关注”类),每个按钮之间有一个随机时间......

javascript: (function() {
    var unfollowButtons = $('button.Unfollow');
    var index = unfollowButtons.length - 1;
    unfollow();

    function unfollow() {
        if (index >= 0) {
            $(unfollowButtons[index--])
                .click();
            setTimeout(unfollow, Math.floor((Math.random() * 1000) + 500));
        }
    }
})();

一旦完成循环,我想再次运行上述函数两次。

再次运行该函数会导致它与第一个函数调用并行运行。

如何在不并行运行的情况下运行 unfollow() 函数 2 或 3 次?

以这种方式尝试(使用ES6 Promises ):

var runUnfollow = function() {
  return new Promise(function(resolve, reject){
    var index = unfollowButtons.length - 1;

    // fencepost for the loop
    var p = Promise.resolve();

    // we stop execution at `i == 0`
    for (var i = index; i >= 0; i--) {
      // run the promise
      // then set `p` as the next one
      p = p.then(unfollowTimeout.bind(null, i));
    }
    // make sure we run the last execution at `i == 0`.
    p.then(function(){
      resolve();
    })

    function unfollowTimeout(i){
      // return a promise to run `unfollow` and a `setTimeout`
      return new Promise(function(resolve,reject){
         unfollow(i);
         setTimeout(resolve, Math.floor((Math.random() * 1000) + 500));
      })
    }
    function unfollow(i) {
      $(unfollowButtons[i])
        .click();
    }
  })
}

// run three times synchronously
runUnfollow().then(runUnfollow).then(runUnfollow).then(function(){
  //finished
});

// another way to run three times synchronously
p = runUnfollow();
for(i=3; i > 0; i--){
  p = p.then(runUnfollow);
}
p.then(function(){
  //finished
});

// run in parallel
Promise.all([runUnfollow, runUnfollow, runUnfollow])
  .then(function(){
    //finished
  });

编辑:返回并再次阅读您的问题,意识到您正在尝试多次运行所有内容 我已经编辑以反映这一点。

只需在单击每个按钮后重置index并重新启动:

javascript: (function() {
    var unfollowButtons = $('button.Unfollow');
    var index = unfollowButtons.length - 1;
    var totalRuns = 3;
    unfollow();

    function unfollow() {
        if (index < 0 && totalRuns) {
            totalRuns--;
            unfollowButtons = $('button.Unfollow');
            index = unfollowButtons.length - 1;
        }

        if (index >= 0) {
            $(unfollowButtons[index--])
                .click();
            setTimeout(unfollow, Math.floor((Math.random() * 1000) + 500));
        }
    }
})();

你应该看看Promises

在函数执行的最后解析你的Promise并再次调用你的函数。 你应该很擅长这个。

你有2个选择

1.使用用户脚本

为此,您需要一个用户脚本扩展管理器,例如 Chrome 的 Tampermonkey、Firefox 的 Greasemonkey 等。

但既然你想要一个书签,就留下吧。

2.修改Bookmarklet如下

unfollow功能中添加此代码

即检查index是否达到 0 以及是否设置了标志。

FLAG很重要,否则它会创建一个不定式递归循环。

首先在unfollow功能之外将FLAG设置为 0。

然后在unfollow函数中,如果FLAG为 0, index为 0,则启动下一次迭代并将FLAG设置为 1。

if(index < 0 && FLAG==0){
      var unfollowButtons = $('button.Unfollow');
      FLAG=1;
      var index = unfollowButtons.length - 1;
      unfollow();
}

所以,它看起来像这样。

javascript: (function() {
    var unfollowButtons = $('button.Unfollow');
    var index = unfollowButtons.length - 1;
    var FLAG=0;
    unfollow();

    function unfollow() {
        if (index >= 0) {
            $(unfollowButtons[index--])
                .click();
        if(index < 0 && FLAG==0){
             unfollowButtons = $('button.Unfollow');
             FLAG=1;
             index = unfollowButtons.length - 1;
             unfollow();
        }
            setTimeout(unfollow, Math.floor((Math.random() * 1000) + 500));
        }
    }
})();

如果你想总共做 3 次, if(index < 0 && FLAG<=2){FLAG=1更改为FLAG +=1

在您的特定情况下,您可以简单地构建一个数组,其中每个按钮包含两次:

// turn the jQuery selection into a regular array :
var unfollowButtons = $('button.Unfollow').get();

// build a new array, which contains two copies of the above selection :
unfollowButtons = unfollowButtons.concat(unfollowButtons);

据我了解您的要求,可以这样做:

javascript: (function() {
    var unfollowButtons = $('button.Unfollow');
    var index = unfollowButtons.length - 1;
    unfollow();
    var runForNoOfTime = 3;
    var runningForTime = 1;
    function unfollow() {
        if (index >= 0) {
            $(unfollowButtons[index--]).click();
            setTimeout(unfollow, Math.floor(Math.random() * 1000) + 500));

        }else if(runningForTime < runForNoOfTime){
               runningForTime++;
               unfollowButtons = $('button.Unfollow'); //if buttons with class 'Unfollow' changes.
               index = unfollowButtons.length - 1;
               setTimeout(unfollow, Math.floor(Math.random() * 1000) + 500));
            }
    }
})();

您可以使用递归来实现按顺序多次运行您的函数的预期效果。 这是如何做到的:

(function() {
    var unfollowButtons = $('button.Unfollow');
    var index = unfollowButtons.length - 1;

    function unfollow(callback) {
        if (index >= 0) {
            $(unfollowButtons[index--]).click();
        }

        callback();
    }

    function handleUnfollow(maxIter, iter) {
        iter = typeof iter === "number" ? iter : 0;

        if ( iter >= maxIter ) {
            // base case reached, stop further recursive calls
            return true;
        }

        // call unfollow once
        unfollow(function() {
            setTimeout(function() {

                // recursive call
                handleUnfollow(maxIter, ++iter);

            }, Math.floor((Math.random() * 1000) + 500));
        });
    }

    // execute recursive function, which will iterate 2 times
    handleUnfollow(2);
})();

据我所知 Javascript 在单个线程上运行,因此没有发生实际的并行处理。

如果你只是想让函数自己运行 x 次,那么使用递归:

function DoSomething(steps) {    
    // Do stuff here
    steps--;
    if (steps <== 0) {
        return;
    }
    DoSomething(steps);
}

如果您希望事情与 Javascript 以“并行”运行,那么也许您可以考虑使用一些外部代码来管理线程并并行执行多个 Javascript 进程(尽管我不确定这是否可行,如果是,您是否能够让脚本同时访问相同的数据或相互交谈)。

我将当前代码作为块并添加了包装器逻辑。 检查这是否有效。

 (function() { var iterations = 2; unfollowBlock(); function unFollowBlock() { if (iterations-- >0) { var unfollowButtons = $('button.Unfollow'); var index = unfollowButtons.length - 1; unfollow(); function unfollow() { if (index >= 0) { $(unfollowButtons[index--]) .click(); setTimeout(unfollow, Math.floor((Math.random() * 1000) + 500)); } else { //index=-1 end of unfollowblock setTimeout(unFollowBlock, Math.floor((Math.random() * 1000) + 500)); } } } } })();

声明一个标志/检查变量,例如。 var isCycleComplete;

var isCycleComplete = false;

if(isCycleComplete){ // if true runs unfollow function twice
 unfollow();
 unfollow(); 
 isCycleComplete = false; // resets flag
}
else{ // if false
 unfollow();
 isCycleComplete = true; //sets flag to true
}

我不是 javascript 专家,但看看这个简单的片段是否对你有帮助。

function DoSomething(steps) {

// Do stuff here steps--;
 if (steps <
== 0) {
 return;
 } DoSomething(steps);
 }  

试试这个希望它会有用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM