Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
261 views
in Technique[技术] by (71.8m points)

javascript - Nightmare.js error: Search failed: Nothing responds to "goto"

I am running into an error, when including vanilla JS in nightmare.js. I want to make sure that every email in my array is inputted into the system. A for loop would be ideal, but I have continually run into error such as:

Search failed: Nothing responds to "goto"

Here is my code:

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

var siteName = "*********";
var username = "*********";
var password = "*********";

var outboundEmailArray = [
  {
    "from_name": "TestOutbound",
    "email_username": "array1",
    "email_domain": "salesforce.com",
    "email_domain": "salesforce.com",
    "reply_to": "[email protected]"
  },
  {
    "from_name": "Tester",
    "email_username": "array2.0",
    "email_domain": "salesforce.com",
    "email_domain": "salesforce.com",
    "reply_to": "[email protected]"
  }
];
//
// var outboundEmailSetup = function(outboundEmail){
//     nightmare
//     .goto("https://" + siteName + ".desk.com/login/new")
//     .type("input[id='user_session_email']", username)
//     .type("input[id='user_session_password']", password)
//     .click("#user_session_submit").wait(2000)
//     .goto("https://" + siteName + ".desk.com/admin/settings/mail-servers")
//     .click("#a-add-modal").wait(2000)
//     .type("input[id='postmark_outbound_mailbox_fromname']", outboundEmail.from_name).wait(2000)
//     .type("input[id='email_username']", outboundEmail.email_username).wait(2000)
//     .click("#from_select_4999").wait(2000)
//     .type("input[id='postmark_outbound_mailbox_reply_to']", outboundEmail.reply_to).wait(2000)
//     .click("#postmark_commit").wait(2000)
//     .click(".a-modal-bottom .a-button").wait(2000)
//     .evaluate(function() {})
//     .end()
//     .then(function(result) {
//         console.log(result)
//     })
//     .catch(function(error) {
//         console.error('Search failed:', error);
//     });
//   }

var outboundEmailSetup = function(i){
  if(i < outboundEmailArray.length) {
    nightmare
    .goto("https://" + siteName + ".desk.com/login/new")
    .type("input[id='user_session_email']", username)
    .type("input[id='user_session_password']", password)
    .click("#user_session_submit").wait(2000)
    .goto("https://" + siteName + ".desk.com/admin/settings/mail-servers")
    .click("#a-add-modal").wait(2000)
    .type("input[id='postmark_outbound_mailbox_fromname']", outboundEmailArray[i].from_name).wait(2000)
    .type("input[id='email_username']", outboundEmailArray[i].email_username).wait(2000)
    .click("#from_select_4999").wait(2000)
    .type("input[id='postmark_outbound_mailbox_reply_to']", outboundEmailArray[i].reply_to).wait(2000)
    .click("#postmark_commit").wait(2000)
    .click(".a-modal-bottom .a-button").wait(2000)
    .evaluate(function() {})
    .end()
    .then(function(result) {
        console.log(result)
    })
    .catch(function(error) {
        console.error('Search failed:', error);
    });
    outboundEmailSetup(i+1);
  }
}

outboundEmailSetup(0);

Ideally, it would loop through the outboundEmailArray, run the function to input the emails into the system, repeat until it has reached the end of the array.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The key is to avoid multiple calls to the then method concurrently

You will find a very detailed explanation about that concept here.

Basically what you have to do is make sure each consecutive call take place within the previous call then method

This is really straightforward when we know beforehand how many steps we are dealing with. For example, if we want to make two consecutive calls, the code would be like this:

nightmare.goto('http://example.com')
  .title()
  .then(function(title) {
    console.log(title);
    nightmare.goto('http://google.com')
      .title()
      .then(function(title) {
        console.log(title);
      });
  });

Notice how the goto to google.com is inside the then callback.

Since you're dealing with a loop, your code would be a little more sophisticated.

var urls = ['http://example1.com', 'http://example2.com', 'http://example3.com'];
urls.reduce(function(accumulator, url) {
  return accumulator.then(function(results) {
    return nightmare.goto(url)
      .wait('body')
      .title()
      .then(function(result){
        results.push(result);
        return results;
      });
  });
}, Promise.resolve([])).then(function(results){
    console.dir(results);
});

I think the source link explains this code better than I can :-)

The above executes each Nightmare queue in series, adding the results to an array. The resulting accumulated array is resolved to the final .then() call where the results are printed.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...