6

I am using Chromeless to retrieve a piece of information on a website and load a corresponding file:

async function run() {
  const chromeless = new Chromeless()

      const screenshot = await chromeless
        .goto('http://www.website.com')
         title = await chromeless.inputValue('input[name="title"]')

         var fs = require('fs');
         var data = fs.readFileSync(title,"utf8");
         ...
    await chromeless.end()
}

but the file read instructions are executed immediately when I launch the script and do not wait for the web crawling to be finished.

In javascript I think I would need to use callback functions to prevent that but is there a better way to do this with Chromeless?

Sulli
  • 643
  • 8
  • 25
  • see if this helps: https://github.com/graphcool/chromeless/issues/307 – v.coder Jan 12 '18 at 03:49
  • @v.coder it could probably help but it's a bit too technical for me. I don't know what is "event", what is "context"... A simpler example would be greatly appreciated! Or maybe it's possible to run Chromeless without being asynchronous? (I come from Casperjs and didn't have this problem) – Sulli Jan 12 '18 at 04:26
  • The quoted code is missing the `.screenshot()` method call that needs to be chained onto the `.goto()` action, in order for a screenshot to be saved. It seems that in general, Chromeless does not wait (the `await` keyword does not have the expected effect) unless the last method in the chain is one that returns a useful value, such as a screenshot path. (Also, there can only be one such command in each chain.) Therefore, the `await chromeless.inputValue('input[name="title"]')` statement would execute before navigation to the website would be done. – Otto G Apr 19 '18 at 14:50

2 Answers2

3

You can try passing implicitWait: true to the Chromeless constructor. This value is false by default. Setting this to true will make Chromeless wait for elements to exist before executing commands.

In other words, var fs = require('fs'); shouldn't get executed until const title is assigned.

async function run() {
  const chromeless = new Chromeless({implicitWait: true})
  const screenshot = await chromeless.goto('http://www.website.com')
  const title = await chromeless.inputValue('input[name="title"]')

  var fs = require('fs');
  var data = fs.readFileSync(title,"utf8");
  ...
  await chromeless.end()
}
grizzthedj
  • 5,879
  • 14
  • 37
  • 53
  • So what happened is I lost the file I was working on and had to recode everything from scratch. When this was done, the require('fs') bit was only executed after const title was assigned even *without* implicitWait: true . I have no idea why. I couldn't test your answer but I'll mark it as the right answer as it seems to be what I needed. – Sulli Feb 09 '18 at 06:11
  • @Sulli this is probably because you did not omit the `.screenshot()` method after `.goto` when recreating the code. However, if the input field had been loaded with AJAX, after the web page had loaded and the screenshot had been taken, it would have been necessary to wait for the element, using either `implicitWait`, or a `.wait()` method chained before the `.inputValue()` method. – Otto G Apr 19 '18 at 14:57
0

I you are trying to execute code a certain time in advance or upon an event then callbacks are the preferred way to do this. But JS is an asynchronous language. Honestly I don't use it much, but it seems like you could just make any type of async call and you wouldn't be blocked by the code anymore. Just breakout a function from your job that runs the blocking line, and it should run next to the current process. Possibly adding a sleep to ensure it's not going to keep your other code from running.

Ponyisasquare
  • 149
  • 1
  • 1
  • 12