Monday, July 3, 2017

Running a jQuery function multiple times sequentially (for a Bookmarklet)

Leave a Comment

I've got the following jQuery code which I use in a Bookmarklet. It clicks on all the buttons on the page (with the class "Unfollow") one by one, with a random time between each one...

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));         }     } })(); 

I'd like to run the above function again twice once it has completed its cycle.

Just running the function again causes that to run in parallel with the first function call.

How do I run the unfollow() function 2 or 3 times without them all running in parallel?

11 Answers

Answers 1

Try it this way (using 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.then(runUnfollow); } p.then(function(){   //finished });  // run in parallel Promise.all([runUnfollow, runUnfollow, runUnfollow])   .then(function(){     //finished   }); 

EDIT: Went back and read your question again, realized you were trying to run everything multiple times. I've edited to reflect that.

Answers 2

Just reset index and restart after each button is clicked:

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

Answers 3

You should look at Promises.

Resolve your Promise at your function's execution's very end and call your function again. You should be good with that.

Answers 4

In your specific case, you could simply build an array which contains twice each button :

// 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); 

Answers 5

You have 2 options

1.Use a User Script

For that, you need a User Script extension manager, for example Tampermonkey for Chrome, Greasemonkey for Firefox, etc.

But since you want a bookmarklet, just leave it.

2.Modify the Bookmarklet a little as follows

Add this code inside the unfollow function

That is check whether index reached 0 and also the flag is set or not.

FLAG is important otherwise it will create a infinitive recursion loop.

First set FLAG to 0 outside of unfollow function.

Then in unfollow function, if the FLAG is 0 and index is 0, initiate the next iteration and Set FLAG to 1.

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

So, it will look like this.

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));         }     } })(); 

If you want to do it totally 3 times, change if(index < 0 && FLAG<=2){ and FLAG=1 to FLAG +=1

Answers 6

As i understand your requirements it can be done like this :

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));             }     } })(); 

Answers 7

You can use recursion to achieve the desired effect of running your function multiple times sequentially. Here's how this can be done:

(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); })(); 

Answers 8

As far as I'm aware Javascript runs on a single thread, so there is no actual parallel processing taking place.

If you just simply want the function to run itself x times then use recursion:

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

If you want things to run in "parallel" with Javascript then perhaps you could look into having some external code that manages threads and executes multiple Javascript processes in parallel (although I'm not sure if this is possible, and, if it is, whether you'll be able to have the scripts accessing the same data at the same time or talking to eachother).

Answers 9

I have made the current code as block and added wrapper logic. Check if this works.

(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));              }          }       }    }  })();

Answers 10

Declare a flag/check variable eg. var isCycleComplete;

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

M not a pro at javascript but See if this simple snippet helps you.

Answers 11

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

try this hope it will be useful.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment