簡體   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