2017-09-29 4 views
3

J'essaie de passer une variable à .evaluate afin que je puisse les utiliser dans le cadre de la page Web, mais je ne peux pas l'obtenir à travail. Pour cela, j'obtiens Cannot read property 'match' of undefined. J'ai ensuite essayé:Javascript ne peut pas passer Vars/Fn à .evaluate() Scope (NightmareJS)

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]); 
      } 
     } 
    }); 

Avec le même résultat. J'ai ensuite essayé:

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(); 

Pour cela, la première itération de la boucle est exécutée et matchResult[1] est connecté à la console. Je reçois alors Error: Evaluation timed out after 30000msec. Are you calling done() or resolving your promises?.

J'ai aussi essayé quelque chose comme ceci:

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(); 

qui ne passe le retour à .then() mais comment puis-je passer le tableau dans la prochaine évaluation? Et maintenant, c'est la dernière chose que je peux penser, mais ne fonctionne pas:

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(); 

J'ai trouvé une solution here mais il retourne undefined pour moi. J'ai également trouvé this qui parle d'une chose similaire dans PhantomJS mais qui n'a pas encore trouvé de code fonctionnel.

+4

'Array.prototype.forEach' renvoie' undefined'. Utilisez ['Array.prototype.find'] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find). –

+0

Qu'est-ce que 'nightmare.evaluate'? Ce que vous avez ne ressemble pas à une promesse, qui est la seule chose que 'l'attente 'peut contrôler. La façon dont vous vous attendriez, au moins. – Andrew

+0

J'ai mis à jour la question avec un meilleur exemple du problème et plusieurs versions du code que j'ai fatigué. J'ai été capable de résoudre le code précédent que j'ai posté en utilisant 'Array.prototype.find' mais le code que j'ai dû écrire immédiatement après souffre du même genre de problème que' find' ne corrigera pas. – xendi

Répondre

1

J'ai trouvé la réponse. Il semble que la moitié de mes tentatives fonctionnent probablement et je ne m'en suis pas rendu compte. Dans la portée de .evaluate(), nous sommes dans la portée du navigateur (comme prévu) mais je ne considérais pas que je ne pouvais pas me connecter à la console à partir de cette portée. Plus précisément, je ne peux pas me connecter à ma console. Si j'exécute console.log à partir de cette étendue, il se connecte à la console du navigateur. Le code suivant fonctionne:

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! 

Je pense que cela résout. Il pourrait être un peu difficile de déboguer ce qui se passe dans la portée du document, mais certainement possible.