RetroCode
RetroCode

Reputation: 332

Asynchronicity issues with NightmareJS

I am trying to build a script using nightmarejs that would be able to click a button over and over again , like that youtube button that's at the bottom of the comments section which loads older comments each time you press it (example: youtube.com/watch?v=pZISJqJbQuU&list=RDpZISJqJbQuU#t=3) and stop when there is no more button to be clicked.

I have tried calling evaluate , only for end() method to be called first and cancel the process . I have tried using setTimeout , setInterval , then(), converting the loop into a recursion. Everytime either evaluate() will complete it's job but not quit (just hanging) or quit before completing it's job because of a race condition with end().

Is there any experienced nightmarejs user out there ?

    function youtube_button_clicker(group) {
    var nightmare = Nightmare({
        show: true
    });

    nightmare
        .goto(url)
        .inject('js', 'jquery-3.1.0.js')
        .then(
            () => nightmare.
         evaluate(function() {
    for (i=0;i>LEN;i++)
    { setTimeout(() => { $(button_element).click() }, i * 2000); }


    return "done"


}))
.catch(function (error) {

        console.error('Search failed:', error);
    });

}

Remove the .end() method and it hangs, put the .end() back again and it skips the process - quits early. What can I do ?

Upvotes: 1

Views: 542

Answers (1)

Ross
Ross

Reputation: 2468

.evaluate() functions cannot be asynchronous, at least not until #819 (or something like it) is included. In other words, evaluating with setTimeout() is not going to work. Additionally, I don't think that would be a particularly good route to go in this case, even if it were possible out of the box.

As an aside, you might want go give this example in nightmare-examples a read. It gives a brief primer on chaining multiple operations and looping.

You could probably get away with a recursive function, but you'll have to be careful to enforce a stop condition. (You may also want to have a look at #625, the action is scrolling but the problem is similar.) From the hip, I think something like this might get you close:

var iterations = 0;
var reclick = function(nm) {
  return nm
    .click('#some-button')
    .wait('#element-you-check-for')
    .then(function() {
      // you could also use `.visible()` or something before this `.then()`
      // depends on your use case
      // here, I'm using the number of iterations
      if (iterations++ < 10) {
        return reclick(nm);
      }
      return;
    });
}

nightmare
  .goto('http://my-domain.tld')
  .then(function() {
    return reclick(nightmare);
  })
  .then(function(){
    // ... other actions
  })

Upvotes: 1

Related Questions