2017-09-29 58 views
3

我试图将一个变量传递给.evaluate,因此我可以在网页范围内使用它们,但是我无法获取它工作。Javascript不能将变量传递给.evaluate()范围(NightmareJS)

await nightmare.evaluate(function() { 
     let links = document.querySelectorAll('div.fsl a'); 
     return Array.prototype.map.call(links, function(e) { 
      return e.getAttribute('href'); 
     }); 
    }) 

    .evaluate(function(result) { 
     for(var i = 0; i < result.length; i++) { 
      var matchResult = result[i].match(/.com\/(.*?)\?fref/); 
      if (matchResult) { 
       console.log(matchResult[1]); 
      } 
     } 
    }); 

为此我得到Cannot read property 'match' of undefined。我然后尝试:

const evaluated = await nightmare.evaluate(function() { 
     let links = document.querySelectorAll('div.fsl a'); 
     return Array.prototype.map.call(links, function(e) { 
      return e.getAttribute('href'); 
     }); 
    }); 

    await nightmare.evaluate(function(evaluated) { 
     for(var i = 0; i < evaluated.length; i++) { 
      var matchResult = evaluated[i].match(/.com\/(.*?)\?fref/); 
      if (matchResult) { 
       console.log(matchResult[1]); 
      } 
     } 
    }); 

具有相同的结果。然后我想:

const evaluated = await nightmare.evaluate(function() { 
     let links = document.querySelectorAll('div.fsl a'); 
     return Array.prototype.map.call(links, function(e) { 
      return e.getAttribute('href'); 
     }); 
    }); 

for(var i = 0; i < evaluated.length; i++){ 
     var matchResult = evaluated[i].match(/.com\/(.*?)\?fref/); 
     if(matchResult) { 
      console.log(matchResult[1]); 
      await nightmare.evaluate(function(matchResult) { 
       return document.body.innerHTML += '<a href="https://www.example.com/'+matchResult[0]+'">'+matchResult[0]+'</a>'; 
      }); 
      await nightmare.click('a[href="https://www.example.com/'+matchResult[0]+'"]'); 
      await nightmare.wait(5000); 
     } 
    } 
await nightmare.end(); 

为此,循环的第一次迭代被执行,matchResult[1]登录到控制台。然后我得到Error: Evaluation timed out after 30000msec. Are you calling done() or resolving your promises?

我也尝试过这样的事情:

await nightmare.evaluate(function() { 
     let links = document.querySelectorAll('div.fsl a'); 
     return Array.prototype.map.call(links, function(e) { 
      return e.getAttribute('href'); 
     }); 
    }).then(function(users){ 

    }).end(); 

这也传递回.then()但如何传递数组到下一个评价?而现在,这是我能想到的最后一件事,但不工作:

await nightmare.evaluate(function() { 
     let links = document.querySelectorAll('div.fsl a'); 
     return Array.prototype.map.call(links, function(e) { 
      return e.getAttribute('href'); 
     }); 
    }).evaluate((users) => { 
     console.log(users); 
    }).end(); 

我找到了解决办法here,但它为我返回undefined。我也发现了this,它谈到了PhantomJS中类似的东西,但还没有提出一个可行的代码。

+4

'Array.prototype.forEach'返回'undefined'。使用['Array.prototype.find'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find)。 –

+0

什么是'nightmare.evaluate'?你有什么看起来不像是一个承诺,这是“等待”可以控制的唯一一件事。至少,你会期望的方式。 – Andrew

+0

我已经更新了问题,并提供了一个更好的问题示例以及我累了的几个代码版本。我能够通过使用'Array.prototype.find'来解析我发布的以前的代码,但是我必须立即编写的代码遭受类似于“find”无法修复的问题的困扰。 – xendi

回答

1

我找到了答案。似乎有一半的尝试可能是在工作,我只是没有意识到这一点。在.evaluate()的范围内,我们处于浏览器范围内(按照预期),但我没有考虑到我无法从该范围登录到控制台。具体来说,我无法登录到我的控制台。如果我从该范围运行console.log,它将记录到浏览器控制台。下面的代码工程:

var foo = "stuff"; 
    var bar = "stuff for the remote page"; 

    var result = await nightmare.evaluate(function(bar2) { 
     // this function executes in the remote context 
     // it has access to the DOM, remote libraries, and args you pass in 
     console.log("bla "+bar2); // this will not output 
     // but not to outer-scope vars 
     return typeof foo + " " + bar2; 
    }, bar); 
    console.log(result); // this logs bar2! 

我认为这解决了它。调试文档范围内发生的情况可能有点棘手,但当然可能。