nightmare icon indicating copy to clipboard operation
nightmare copied to clipboard

How to use async/await syntax with .use() method

Open mateuszroth opened this issue 8 years ago • 1 comments

I can't find an answer to my issue so I have to ask here.

I have got a single file with several functions and a Nightmare's instance used in every function. Code uses async/await syntax. Something like:

const botSettings = { ... } // some custom settings
const botInstance = nightmare(botSettings)

const functionOne = async (target, text) => {
  await botInstance
    .wait(target)
    .wait(1000)
    .type(target, '')
    .type(target, text)

  ...
  await doSomethingInDatabase()

  return botInstance
    .wait(1000)
    .click('#send')
}

const functionTwo = async () => {
  await botInstance
    .goto('http://website.com')
    .wait(5000)

  await functionOne('selector', 'Hello world')

  await botInstance
    .click('.selector')
    .wait(5000)

  const importantValue = await getTextFromTarget('#userdata')

  ...
  // save and get something from database

  // another bot actions
  ...
}

const getTextFromTarget = async (target) => {
  await botInstance
    .wait(target)
    .evaluate(function (target) {
      const targetNode = document.querySelector(target)
      if (targetNode) {
        return targetNode.innerText
      }
      return ''
    }, target)
    .then(function (result) {
      text = result
    })

  await doSomethingInDatabase()

  return text
}

I want to split this file into files with separated functions and I know that I have to use Nightmare .use method to pass Nightmare's instance correctly.

I've tried:

const functionOne = (target, text) => {
  return nightmare => {
    ...
  }
}

and then in main file:

...
await botInstance.use(functionOne('selector', 'Hello world'))
...

But I can't find any other way to use it than rewriting function to Promise syntax from async/await syntax. Is there a way to write it like below:

const functionOne = (target, text) => {
  return async nightmare => {
    await nightmare
      .wait(target)
      .wait(1000)
      .type(target, '')
      .type(target, text)

    ...
    await doSomethingInDatabase()

    return nightmare
      .wait(1000)
      .click('#send')
  }
}

and then in main file:

...
await botInstance.use(await functionOne('selector', 'Hello world'))
...

Or am I doing something wrong?

mateuszroth avatar Oct 18 '17 14:10 mateuszroth

Hi @mateuszroth, unfortunately this is not yet possible, since use is synchronously queueing up actions to be executed later, but async/await would make that async. it should be pretty simple to add though.

In the meantime, I'd take a look at using a custom action to accomplish your task.

matthewmueller avatar Feb 16 '18 08:02 matthewmueller