Nightmarejs inside meteor Can't return method result

I am using nightmarejs in my meteor server methods to scrape a website and returns the data into the client.

But the problem is i am not able to get any data back from the server. It console.log the result in the server. It just that i can’t get it in the client side Method.call function.

1 Like

Ok, I think this is because of the asynchronous execution of the nightmare code in the meteor methods.
Anyway to make it synchronous, so i get the result in the client method call?

Sure, use e.g. the promise api that nightmarejs offers and ‘await’ its return in the method.

Am on mobile but if you post some code, I’ll help out a bit later.

Try the following (I haven’t tested this):

var Nightmare = require('nightmare'),
  nightmare = Nightmare({
    show: true
  });

Meteor.methods({
  'its.a.nightmare'() {
    const promise = nightmare
      //load a url
      .goto('http://yahoo.com')
      //simulate typing into an element identified by a CSS selector
      //here, Nightmare is typing into the search bar
      .type('input[title="Search"]', 'github nightmare')
      //click an element identified by a CSS selector
      //in this case, click the search button
      .click('#uh-search-button')
      //wait for an element identified by a CSS selector
      //in this case, the body of the results
      .wait('#main')
      //execute javascript on the page
      //here, the function is getting the HREF of the first search result
      .evaluate(function() {
        return document.querySelector('#main .searchCenterMiddle li a').href;
      })
      //run the queue of commands specified, followed by logging the HREF
      .then(function(result) {
        console.log(result);
      })
      //run the queue of commands specified
      //in this case, `.end()`
      .then(function() {
        console.log('done');
      })
      //catch errors if they happen
      .catch(function(error){
        console.error('an error has occurred: ' + error);
      });
    return promise.await();
  }
});
1 Like

Thanks.

I was missing a return keyword before the nightmare code. I thought the return inside the then function will sent the response to client. I’ll try your code. Its working now.

1 Like

I am just returning the nightmare like this:

return nightmare
      //load a url
      .goto('http://yahoo.com');
      

and its working.

Is there any difference in both? I don’t know much about promises. Even though i uses it.

That’s fine. Meteor automatically resolves Promises before returning from the method :slight_smile:

@robfallows Thanks. Then i guess what @tomsp suggested is the manual way of doing it.

I think it just overcomplicates things when you try to work around a problem that doesn’t exist :slight_smile:

1 Like

@robfallows I didn’t know it automatically resolves the promises. Do you know since when by any chance? Is it documented? Anyways, Meteor is awesome :slight_smile:

@nisthar glad you got it working. And even simpler than my suggestion. Nice!

1 Like

Hmm. Not sure when this was introduced, but it’s been like this for quite a while - at least a year, I think.

To add to the fun, you can also have async methods:

Meteor.methods({
  async myMethod(param) {
    const a = await someAsyncFunction(param);
    return await someOtherAsyncFunction(a);
  }
});
2 Likes

That does look like fun. Reminds me of the good old waterfall function from the async npm lib. In case you need to write node.js code w/o Meteors magic.

1 Like