JavaScript Nightmare conditional wait()

I'm trying to crawl a webpage using Nightmare, but want to wait for #someelem to be present, only if it actually exists. Otherwise, I want Nightmare to move on. How can this be done using .wait()?

I can't use .wait(ms). Using .wait(selector) means Nightmare will keep waiting until the element is present, but if the page will never have this element, Nightmare will keep waiting forever.

The last option is to use .wait(fn). And I've tried something like this

.wait(function(cheerio) {
            var $ = cheerio.load(document.body.outerHTML);
            var attempt = 0;

            function doEval() {
                if ( $('#elem').length > 0 ) {
                    return true;
                }
                else {
                    attempt++;

                    if ( attempt < 10 ) {
                        setTimeout(doEval,2000); //This seems iffy.
                    }
                    else {
                        return true;
                    }
                }
            }

            return doEval();
        },cheerio)

So, wait and attempt again (upto a threshold), and if the element is not found, then just move on. The code seems wrong around setTimeout, because .wait is done at the browser-scope.

Thanks in advance!

Answer:1

I don't think passing the cheerio library as you have it is going to work very well. The arguments get serialized (more or less) to be passed to the child Electron process, so passing an entire library probably won't work.

On the up side, the fn part of .wait(fn) is executed in the page context - meaning you have full access to document and the methods it has (eg, querySelector). You could also have access to the page's jQuery context if it exists, or you could even use .inject() to inject it if not.

Setting that aside, you're right insofar as .wait() (and .evaluate(), for that matter) expect a synchronous method, at least until something like promises could be used directly in .evaluate().

Until that is available, you could use .action() to mimic the behavior you want:

var Nightmare = require('nightmare');

Nightmare.action('deferredWait', function(done) {
  var attempt = 0;
  var self = this;

  function doEval() {
    self.evaluate_now(function(selector) {
      return (document.querySelector(selector) !== null);
    }, function(result) {
      if (result) {
        done(null, true);
      } else {
        attempt++;
        if (attempt < 10) {
          setTimeout(doEval, 2000); //This seems iffy.
        } else {
          done(null, false);
        }
      }
    }, '#elem');
  };
  doEval();
  return this;
});

var nightmare = Nightmare();
nightmare.goto('http://example.com')
  .deferredWait()
  .then(function(result) {
    console.log(result);
  });
Answer:2
  1. As mentioned in documentation of nightmarejs,

.wait(selector) Wait until the element selector is present e.g. .wait('#pay-button')

the wait wait works in this case only till the element first becomes visible if it does not then it will work till default timeout of 30s

  1. wait with function

    .wait(function () { return (document.querySelector(selector) === null); })

where selector is the element based on whose existence in the DOM we wait.

Answer:3

I'm trying to figure out how to trigger a link button to trigger and change all checkboxes to checked when clicked upon. When I click the button, it will bring up the alert message, but not triggering ...

I'm trying to figure out how to trigger a link button to trigger and change all checkboxes to checked when clicked upon. When I click the button, it will bring up the alert message, but not triggering ...

  1. trigger check checkbox jquery
  2. trigger checkbox check
  3. trigger checkbox check event

I am currently working on an problem with a login page for an AngularJS app. The login page uses the $http service to submit the username and password using Basic authentication (Authorization: Basic ...

I am currently working on an problem with a login page for an AngularJS app. The login page uses the $http service to submit the username and password using Basic authentication (Authorization: Basic ...

I have this code : var dynamicVarName = id; var percentage = res.parkeren[0].dynamicVarName.percentage; DynamicvarName can have different values, but when i call this in the var percentage it's ...

I have this code : var dynamicVarName = id; var percentage = res.parkeren[0].dynamicVarName.percentage; DynamicvarName can have different values, but when i call this in the var percentage it's ...

I have this component: export class FileFormComponent { _base64: string; handleFile($event){ var input = $event.target; var reader = new FileReader(); reader.onloadend = function() { ...

I have this component: export class FileFormComponent { _base64: string; handleFile($event){ var input = $event.target; var reader = new FileReader(); reader.onloadend = function() { ...

  1. component definition
  2. component to hdmi
  3. component synonym
  4. component form
  5. components of blood
  6. component cable
  7. componentdidupdate
  8. components of fitness
  9. component to hdmi converter
  10. component form of a vector
  11. components of a nucleotide
  12. components of gdp
  13. components of dna
  14. components of physical fitness
  15. component pouch 5e
  16. component speakers
  17. component video
  18. component hardware
  19. components of culture
  20. components of a business plan