2017-09-29 1 views
3

私は変数を.evaluateに渡そうとしていますので、Webページのスコープで使用できますが、作業。JavaScriptはVars/Fnに渡すことはできません。スコープ(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を返します。私はまた、PhantomJSで同様のことについて語っているが、まだ実行可能なコードを思い付いていないthisが見つかりました。

+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! 

これは解決したと思います。ドキュメントのスコープで何が起こっているのかをデバッグするのはちょっと難しいかもしれませんが、確かに可能です。

関連する問題